Пример #1
0
const FileStatusCacheEntry * GitFolderStatus::GetFullStatus(const CTGitPath& filepath, BOOL bIsFolder)
{
	const FileStatusCacheEntry * ret = NULL;

	CString sProjectRoot;
	BOOL bHasAdminDir = g_ShellCache.HasGITAdminDir(filepath.GetWinPath(), bIsFolder, &sProjectRoot);

	//no overlay for unversioned folders
	if (!bHasAdminDir)
		return &invalidstatus;
	//for the SVNStatus column, we have to check the cache to see
	//if it's not just unversioned but ignored
	ret = GetCachedItem(filepath);
	if ((ret)&&(ret->status == git_wc_status_unversioned)&&(bIsFolder)&&(bHasAdminDir))
	{
		// an 'unversioned' folder, but with an ADMIN dir --> nested layout!
		// NOTE: this could be a sub-project in git, or just some standalone project inside of another, either way a TODO
		ret = BuildCache(filepath, sProjectRoot, bIsFolder, TRUE);
		if (ret)
			return ret;
		else
			return &invalidstatus;
	}
	if (ret)
		return ret;

	//if it's not in the cache and has no admin dir, then we assume
	//it's not ignored too
	ret = BuildCache(filepath, sProjectRoot, bIsFolder);
	if (ret)
		return ret;
	else
		return &invalidstatus;
}
Пример #2
0
const FileStatusCacheEntry * GitFolderStatus::BuildCache(const CTGitPath& filepath, const CString& /*sProjectRoot*/, BOOL bIsFolder, BOOL bDirectFolder)
{
	//dont' build the cache if an instance of TortoiseGitProc is running
	//since this could interfere with svn commands running (concurrent
	//access of the .git directory).
	if (g_ShellCache.BlockStatus())
	{
		CAutoGeneralHandle TGitMutex = ::CreateMutex(NULL, FALSE, _T("TortoiseGitProc.exe"));
		if (TGitMutex != NULL)
		{
			if (::GetLastError() == ERROR_ALREADY_EXISTS)
			{
				return &invalidstatus;
			}
		}
	}

	ClearCache();

	if (bIsFolder)
	{
		if (bDirectFolder)
		{
			// NOTE: see not in GetFullStatus about project inside another project, we should only get here when
			//       that occurs, and this is not correctly handled yet

			// initialize record members
			dirstat.status = git_wc_status_none;
			dirstat.askedcounter = GITFOLDERSTATUS_CACHETIMES;
			dirstat.assumeValid = FALSE;
			dirstat.skipWorktree = FALSE;

			dirstatus = NULL;
//			rev.kind = git_opt_revision_unspecified;


			if (dirstatus)
			{
/*				if (dirstatus->entry)
				{
					dirstat.author = authors.GetString (dirstatus->entry->cmt_author);
					dirstat.url = authors.GetString (dirstatus->entry->url);
					dirstat.rev = dirstatus->entry->cmt_rev;
				}*/
				dirstat.status = GitStatus::GetMoreImportant(dirstatus->text_status, dirstatus->prop_status);
			}
			m_cache[filepath.GetWinPath()] = dirstat;
			m_TimeStamp = GetTickCount();
			return &dirstat;
		}
	} // if (bIsFolder)

	m_nCounter = 0;

	git_wc_status_kind status;
	bool assumeValid = false;
	bool skipWorktree = false;
	int t1,t2;
	t2=t1=0;
	try
	{
		git_depth_t depth = git_depth_infinity;

		if (g_ShellCache.GetCacheType() == ShellCache::dll)
		{
			depth = git_depth_empty;
		}

		t1 = ::GetCurrentTime();
		status = m_GitStatus.GetAllStatus(filepath, depth, &assumeValid, &skipWorktree);
		t2 = ::GetCurrentTime();
	}
	catch ( ... )
	{
		status = git_wc_status_unknown;
	}

	CTraceToOutputDebugString::Instance()(_T(__FUNCTION__) _T(": building cache for %s - time %d\n"), filepath.GetWinPath(), t2 - t1);

	m_TimeStamp = GetTickCount();
	FileStatusCacheEntry * ret = NULL;

	if (_tcslen(filepath.GetWinPath())==3)
		ret = &m_cache[(LPCTSTR)filepath.GetWinPathString().Left(2)];
	else
		ret = &m_cache[filepath.GetWinPath()];

	if (ret)
	{
		ret->status = status;
		ret->assumeValid = assumeValid;
		ret->skipWorktree = skipWorktree;
	}

	m_mostRecentPath = filepath;
	m_mostRecentStatus = ret;

	if (ret)
		return ret;
	return &invalidstatus;
}
Пример #3
0
const FileStatusCacheEntry * GitFolderStatus::BuildCache(const CTGitPath& filepath, const CString& sProjectRoot, BOOL bIsFolder, BOOL bDirectFolder)
{
//	svn_client_ctx_t *			localctx;
//	apr_hash_t *				statushash;
//	apr_pool_t *				pool;
    //git_error_t *				err = NULL; // If svn_client_status comes out through catch(...), err would else be unassigned
    git_error_t err = 0;

    //dont' build the cache if an instance of TortoiseProc is running
    //since this could interfere with svn commands running (concurrent
    //access of the .git directory).
    if (g_ShellCache.BlockStatus())
    {
        HANDLE TGitMutex = ::CreateMutex(NULL, FALSE, _T("TortoiseGitProc.exe"));
        if (TGitMutex != NULL)
        {
            if (::GetLastError() == ERROR_ALREADY_EXISTS)
            {
                ::CloseHandle(TGitMutex);
                return &invalidstatus;
            }
        }
        ::CloseHandle(TGitMutex);
    }

//	pool = svn_pool_create (rootpool);				// create the memory pool

    ClearCache();
//	svn_error_clear(svn_client_create_context(&localctx, pool));
    // set up the configuration
    // Note: I know this is an 'expensive' call, but without this, ignores
    // done in the global ignore pattern won't show up.
//	if (g_ShellCache.ShowIgnoredOverlay())
//;//		svn_error_clear(svn_config_get_config (&(localctx->config), g_pConfigDir, pool));

    // strings pools are unused, now -> we may clear them

    authors.clear();
    urls.clear();
    owners.clear();

    if (bIsFolder)
    {
        if (bDirectFolder)
        {
            // NOTE: see not in GetFullStatus about project inside another project, we should only get here when
            //       that occurs, and this is not correctly handled yet

            // initialize record members
//			dirstat.rev = -1;
            dirstat.status = git_wc_status_none;
            dirstat.author = authors.GetString(NULL);
            dirstat.url = urls.GetString(NULL);
            dirstat.owner = owners.GetString(NULL);
            dirstat.askedcounter = GITFOLDERSTATUS_CACHETIMES;
            dirstat.needslock = false;
            dirstat.tree_conflict = false;

            dirstatus = NULL;
//			statushash = apr_hash_make(pool);
//			git_revnum_t youngest = GIT_INVALID_REVNUM;
//			git_opt_revision_t rev;
//			rev.kind = git_opt_revision_unspecified;
            try
            {
                folderpath = filepath;

                /*err = svn_client_status4 (&youngest,
                	filepath.GetDirectory().GetSVNApiPath(pool),
                	&rev,
                	findfolderstatus,
                	this,
                	svn_depth_empty,//depth
                	TRUE,		//getall
                	FALSE,		//update
                	TRUE,		//noignore
                	FALSE,		//ignore externals
                	NULL,
                	localctx,
                	pool);*/
            }
            catch ( ... )
            {
                dirstatus = NULL;
            }


            if (dirstatus)
            {
                /*				if (dirstatus->entry)
                				{
                					dirstat.author = authors.GetString (dirstatus->entry->cmt_author);
                					dirstat.url = authors.GetString (dirstatus->entry->url);
                					dirstat.rev = dirstatus->entry->cmt_rev;
                					dirstat.owner = owners.GetString(dirstatus->entry->lock_owner);
                				}*/
                dirstat.status = GitStatus::GetMoreImportant(dirstatus->text_status, dirstatus->prop_status);
//				dirstat.tree_conflict = dirstatus->tree_conflict != NULL;
            }
            m_cache[filepath.GetWinPath()] = dirstat;
            m_TimeStamp = GetTickCount();
//			svn_error_clear(err);
//			svn_pool_destroy (pool);				//free allocated memory
            return &dirstat;
        }
    } // if (bIsFolder)

    m_nCounter = 0;

    //Fill in the cache with
    //all files inside the same folder as the asked file/folder is
    //since subversion can do this in one step
//	localctx->auth_baton = NULL;

//	statushash = apr_hash_make(pool);
//	git_revnum_t youngest = GIT_INVALID_REVNUM;
//	git_opt_revision_t rev;
//	rev.kind = git_opt_revision_unspecified;

    git_wc_status_kind status;
    int t1,t2;
    t2=t1=0;
    try
    {
        git_depth_t depth = git_depth_infinity;

        if (g_ShellCache.GetCacheType() == ShellCache::dll)
        {
            depth = git_depth_empty;
        }

        t1 = ::GetCurrentTime();
        status = m_GitStatus.GetAllStatus(filepath, depth);
        t2 = ::GetCurrentTime();
    }
    catch ( ... )
    {
    }

    ATLTRACE2(_T("building cache for %s - time %d\n"), filepath.GetWinPath(), t2 -t1);

    // Error present if function is not under version control
    if (err != NULL)
    {
//		svn_error_clear(err);
//		svn_pool_destroy (pool);				//free allocated memory
        return &invalidstatus;
    }

//	svn_error_clear(err);
//	svn_pool_destroy (pool);				//free allocated memory
    m_TimeStamp = GetTickCount();
    FileStatusCacheEntry * ret = NULL;

    if (_tcslen(filepath.GetWinPath())==3)
        ret = &m_cache[(LPCTSTR)filepath.GetWinPathString().Left(2)];
    else
        ret = &m_cache[filepath.GetWinPath()];

    //memset(ret, 0, sizeof(FileStatusCacheEntry));
    ret->status = status;

    m_mostRecentPath = filepath;
    m_mostRecentStatus = ret;

#if 0
    FileStatusMap::const_iterator iter;
    if ((iter = m_cache.find(filepath.GetWinPath())) != m_cache.end())
    {
        ret = &iter->second;
        m_mostRecentPath = filepath;
        m_mostRecentStatus = ret;
    }
    else
    {
        // for SUBST'ed drives, Subversion doesn't return a path with a backslash
        // e.g. G:\ but only G: when fetching the status. So search for that
        // path too before giving up.
        // This is especially true when right-clicking directly on a SUBST'ed
        // drive to get the context menu
        if (_tcslen(filepath.GetWinPath())==3)
        {
            if ((iter = m_cache.find((LPCTSTR)filepath.GetWinPathString().Left(2))) != m_cache.end())
            {
                ret = &iter->second;
                m_mostRecentPath = filepath;
                m_mostRecentStatus = ret;
            }
        }
    }
#endif
    if (ret)
        return ret;
    return &invalidstatus;
}