Esempio n. 1
0
int CCachedDirectory::EnumFiles(const CTGitPath &path , bool IsFull)
{
	CString sProjectRoot;
	path.HasAdminDir(&sProjectRoot);

	CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": EnumFiles %s\n"), path.GetWinPath());

	ATLASSERT( !m_directoryPath.IsEmpty() );

	CString sSubPath;

	CString s = path.GetWinPath();

	if (s.GetLength() > sProjectRoot.GetLength())
	{
		// skip initial slash if necessary
		if(s[sProjectRoot.GetLength()] == _T('\\'))
			sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() -1);
		else
			sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() );
	}

	// strip "\" at the end, otherwise cache lookups for drives do not work correctly
	sProjectRoot.TrimRight(_T("\\"));

	GitStatus *pStatus = &CGitStatusCache::Instance().m_GitStatus;
	UNREFERENCED_PARAMETER(pStatus);
	git_wc_status_kind status = git_wc_status_none;

	if (!path.IsDirectory())
	{
		bool assumeValid = false;
		bool skipWorktree = false;
		pStatus->GetFileStatus(sProjectRoot, sSubPath, &status, IsFull, false, true, GetStatusCallback, this, &assumeValid, &skipWorktree);
		if (status < m_mostImportantFileStatus)
			RefreshMostImportant();
	}
	else
	{
		bool isSelf = path == m_directoryPath;
		if (isSelf)
		{
			AutoLocker lock(m_critSec);
			// clear subdirectory status cache
			m_childDirectories.clear();
			// build new files status cache
			m_entryCache_tmp.clear();
		}

		m_mostImportantFileStatus = git_wc_status_none;
		pStatus->EnumDirStatus(sProjectRoot, sSubPath, &status, IsFull, false, true, GetStatusCallback,this);
		m_mostImportantFileStatus = GitStatus::GetMoreImportant(m_mostImportantFileStatus, status);

		if (isSelf)
		{
			AutoLocker lock(m_critSec);
			// use a tmp files status cache so that we can still use the old cached values
			// for deciding whether we have to issue a shell notify
			m_entryCache = m_entryCache_tmp;
			m_entryCache_tmp.clear();
		}

		// need to set/construct m_ownStatus (only unversioned and normal are valid values)
		m_ownStatus = git_wc_status_unversioned;
		m_ownStatus.SetKind(git_node_dir);
		if (m_mostImportantFileStatus > git_wc_status_unversioned)
		{
			git_wc_status2_t status2;
			status2.text_status = status2.prop_status = git_wc_status_normal;
			m_ownStatus.SetStatus(&status2);
		}
		else
		{
			if (::PathFileExists(m_directoryPath.GetWinPathString() + _T("\\.git"))) {
				git_wc_status2_t status2;
				status2.text_status = status2.prop_status = git_wc_status_normal;
				m_ownStatus.SetStatus(&status2);
			}
			else
			{
				git_wc_status2_t status2;
				status2.text_status = status2.prop_status = CalculateRecursiveStatus();
				m_ownStatus.SetStatus(&status2);
			}
		}
	}

	return 0;
}
Esempio n. 2
0
bool
CCachedDirectory::SvnUpdateMembersStatus()
{
    if (InterlockedExchange(&m_FetchingStatus, TRUE))
        return false;

    svn_opt_revision_t revision;
    revision.kind = svn_opt_revision_unspecified;

    SVNPool subPool(CSVNStatusCache::Instance().m_svnHelp.Pool());
    CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": stat for %s\n"), m_directoryPath.GetWinPath());

    const char * svnapipath = m_directoryPath.GetSVNApiPath(subPool);
    if ((svnapipath == 0)||(svnapipath[0] == 0))
    {
        InterlockedExchange(&m_FetchingStatus, FALSE);
        m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
        CSVNStatusCache::Instance().BlockPath(m_directoryPath, true, 5);
        return false;
    }
    m_pCtx = CSVNStatusCache::Instance().m_svnHelp.ClientContext(subPool);
    svn_error_t * pErr = nullptr;
    if (m_pCtx)
    {
        pErr = svn_client_status5 (
                                   NULL,
                                   m_pCtx,
                                   svnapipath,
                                   &revision,
                                   svn_depth_immediates,
                                   TRUE,       // get all
                                   FALSE,      // update
                                   TRUE,       // no ignores
                                   FALSE,      // ignore externals
                                   TRUE,       // depth as sticky
                                   NULL,       // changelists
                                   GetStatusCallback,
                                   this,
                                   subPool
                                   );

        svn_wc_context_destroy(m_pCtx->wc_ctx);
        m_pCtx->wc_ctx = NULL;
        m_pCtx = NULL;
    }
    else
    {
        CTraceToOutputDebugString::Instance()(__FUNCTION__ ": error creating client context!\n");
        m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
        // Since we only assume a none status here due to the fact that we couldn't get a client context,
        // make sure that this status times out soon.
        CSVNStatusCache::Instance().m_folderCrawler.BlockPath(m_directoryPath, 20);
        CSVNStatusCache::Instance().AddFolderForCrawling(m_directoryPath);
    }
    InterlockedExchange(&m_FetchingStatus, FALSE);
    if (pErr)
    {
        // Handle an error
        // The most likely error on a folder is that it's not part of a WC
        // In most circumstances, this will have been caught earlier,
        // but in some situations, we'll get this error.
        // If we allow ourselves to fall on through, then folders will be asked
        // for their own status, and will set themselves as unversioned, for the
        // benefit of future requests
        CTraceToOutputDebugString::Instance()(__FUNCTION__ ": svn_cli_stat error '%s'\n", pErr->message);
        // No assert here! Since we _can_ get here, an assertion is not an option!
        // Reasons to get here:
        // - renaming a folder with many sub folders --> results in "not a working copy" if the revert
        //   happens between our checks and the svn_client_status() call.
        // - reverting a move/copy --> results in "not a working copy" (as above)
        switch (pErr->apr_err)
        {
        case SVN_ERR_WC_NOT_WORKING_COPY:
            {
                m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
                CSVNStatusCache::Instance().BlockPath(m_directoryPath, true);
            }
            break;
        case SVN_ERR_WC_PATH_NOT_FOUND:
        case SVN_ERR_WC_NOT_FILE:
        case SVN_ERR_WC_CORRUPT:
        case SVN_ERR_WC_CORRUPT_TEXT_BASE:
        case SVN_ERR_WC_UNSUPPORTED_FORMAT:
        case SVN_ERR_WC_DB_ERROR:
        case SVN_ERR_WC_MISSING:
        case SVN_ERR_WC_PATH_UNEXPECTED_STATUS:
        case SVN_ERR_WC_UPGRADE_REQUIRED:
        case SVN_ERR_WC_CLEANUP_REQUIRED:
            {
                m_currentFullStatus = m_mostImportantFileStatus = svn_wc_status_none;
            }
            break;
        default:
            {
                // Since we only assume a none status here due to svn_client_status()
                // returning an error, make sure that this status times out soon.
                CSVNStatusCache::Instance().m_folderCrawler.BlockPath(m_directoryPath, 20);
                CSVNStatusCache::Instance().AddFolderForCrawling(m_directoryPath);
            }
            break;
        }
        svn_error_clear(pErr);

        return false;
    }

    RefreshMostImportant(false);
    return true;
}