예제 #1
0
void CSVNStatusCache::Create()
{
    ATLASSERT(m_pInstance == NULL);
    if (m_pInstance != NULL)
        return;

    m_pInstance = new CSVNStatusCache;

    m_pInstance->watcher.SetFolderCrawler(&m_pInstance->m_folderCrawler);
#define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) goto exit;
#define LOADVALUEFROMFILE2(x) if (fread(&x, sizeof(x), 1, pFile)!=1) goto error;
    unsigned int value = (unsigned int)-1;
    FILE * pFile = NULL;
    // find the location of the cache
    CString path = GetSpecialFolder(FOLDERID_LocalAppData);
    CString path2;
    if (!path.IsEmpty())
    {
        path += L"\\TSVNCache";
        if (!PathIsDirectory(path))
        {
            DeleteFile(path);
            if (CreateDirectory(path, NULL)==0)
                goto error;
        }
        path += STATUSCACHEFILENAME;
        // in case the cache file is corrupt, we could crash while
        // reading it! To prevent crashing every time once that happens,
        // we make a copy of the cache file and use that copy to read from.
        // if that copy is corrupt, the original file won't exist anymore
        // and the second time we start up and try to read the file,
        // it's not there anymore and we start from scratch without a crash.
        path2 = path;
        path2 += L"2";
        DeleteFile(path2);
        CopyFile(path, path2, FALSE);
        DeleteFile(path);
        pFile = _tfsopen(path2, L"rb", _SH_DENYNO);
        if (pFile)
        {
            try
            {
                LOADVALUEFROMFILE(value);
                if (value != CACHEDISKVERSION)
                {
                    goto error;
                }
                int mapsize = 0;
                LOADVALUEFROMFILE(mapsize);
                for (int i=0; i<mapsize; ++i)
                {
                    LOADVALUEFROMFILE2(value);
                    if (value > MAX_PATH)
                        goto error;
                    if (value)
                    {
                        CString sKey;
                        if (fread(sKey.GetBuffer(value+1), sizeof(TCHAR), value, pFile)!=value)
                        {
                            sKey.ReleaseBuffer(0);
                            goto error;
                        }
                        sKey.ReleaseBuffer(value);
                        std::unique_ptr<CCachedDirectory> cacheddir (new CCachedDirectory());
                        if (!cacheddir.get() || !cacheddir->LoadFromDisk(pFile))
                        {
                            cacheddir.reset();
                            goto error;
                        }
                        CTSVNPath KeyPath = CTSVNPath(sKey);
                        if (m_pInstance->IsPathAllowed(KeyPath))
                        {
                            // only add the path to the watch list if it is versioned
                            if ((cacheddir->GetCurrentFullStatus() != svn_wc_status_unversioned)&&(cacheddir->GetCurrentFullStatus() != svn_wc_status_none))
                                m_pInstance->watcher.AddPath(KeyPath, false);

                            m_pInstance->m_directoryCache[KeyPath] = cacheddir.release();

                            // do *not* add the paths for crawling!
                            // because crawled paths will trigger a shell
                            // notification, which makes the desktop flash constantly
                            // until the whole first time crawling is over
                            // m_pInstance->AddFolderForCrawling(KeyPath);
                        }
                    }
                }
            }
            catch (CAtlException)
            {
                goto error;
            }
        }
    }
exit:
    if (pFile)
        fclose(pFile);
    if (!path2.IsEmpty())
        DeleteFile(path2);
    m_pInstance->watcher.ClearInfoMap();
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": cache loaded from disk successfully!\n");
    return;
error:
    if (pFile)
        fclose(pFile);
    if (!path2.IsEmpty())
        DeleteFile(path2);
    m_pInstance->watcher.ClearInfoMap();
    Destroy();
    m_pInstance = new CSVNStatusCache;
    CTraceToOutputDebugString::Instance()(__FUNCTION__ ": cache not loaded from disk\n");
}
예제 #2
0
void CSVNStatusCache::Create()
{
	ATLASSERT(m_pInstance == NULL);
    if (m_pInstance != NULL)
        return;

	m_pInstance = new CSVNStatusCache;

	m_pInstance->watcher.SetFolderCrawler(&m_pInstance->m_folderCrawler);
#define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) goto exit;
#define LOADVALUEFROMFILE2(x) if (fread(&x, sizeof(x), 1, pFile)!=1) goto error;
	unsigned int value = (unsigned int)-1;
	FILE * pFile = NULL;
	// find the location of the cache
	TCHAR path[MAX_PATH];		//MAX_PATH ok here.
	TCHAR path2[MAX_PATH];
	if (SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, path)==S_OK)
	{
		_tcscat_s(path, MAX_PATH, _T("\\TSVNCache"));
		if (!PathIsDirectory(path))
		{
			if (CreateDirectory(path, NULL)==0)
				goto error;
		}
		_tcscat_s(path, MAX_PATH, STATUSCACHEFILENAME);
		// in case the cache file is corrupt, we could crash while
		// reading it! To prevent crashing every time once that happens,
		// we make a copy of the cache file and use that copy to read from.
		// if that copy is corrupt, the original file won't exist anymore
		// and the second time we start up and try to read the file,
		// it's not there anymore and we start from scratch without a crash.
		_tcscpy_s(path2, MAX_PATH, path);
		_tcscat_s(path2, MAX_PATH, _T("2"));
		DeleteFile(path2);
		CopyFile(path, path2, FALSE);
		DeleteFile(path);
		pFile = _tfsopen(path2, _T("rb"), _SH_DENYNO);
		if (pFile)
		{
			try
			{
				LOADVALUEFROMFILE(value);
				if (value != CACHEDISKVERSION)
				{
					goto error;
				}
				int mapsize = 0;
				LOADVALUEFROMFILE(mapsize);
				for (int i=0; i<mapsize; ++i)
				{
					LOADVALUEFROMFILE2(value);	
					if (value > MAX_PATH)
						goto error;
					if (value)
					{
						CString sKey;
						if (fread(sKey.GetBuffer(value+1), sizeof(TCHAR), value, pFile)!=value)
						{
							sKey.ReleaseBuffer(0);
							goto error;
						}
						sKey.ReleaseBuffer(value);
                        std::auto_ptr<CCachedDirectory> cacheddir (new CCachedDirectory());
						if (!cacheddir.get() || !cacheddir->LoadFromDisk(pFile))
						{
                            cacheddir.reset();
							goto error;
						}
						CTSVNPath KeyPath = CTSVNPath(sKey);
						if (m_pInstance->IsPathAllowed(KeyPath))
						{
							// only add the path to the watch list if it is versioned
							if ((cacheddir->GetCurrentFullStatus() != svn_wc_status_unversioned)&&(cacheddir->GetCurrentFullStatus() != svn_wc_status_none))
								m_pInstance->watcher.AddPath(KeyPath, false);

                            m_pInstance->m_directoryCache[KeyPath] = cacheddir.release();

                            // do *not* add the paths for crawling!
							// because crawled paths will trigger a shell
							// notification, which makes the desktop flash constantly
							// until the whole first time crawling is over
							// m_pInstance->AddFolderForCrawling(KeyPath);
						}
					}
				}
			}
			catch (CAtlException)
			{
				goto error;
			}
		}
	}
exit:
	if (pFile)
		fclose(pFile);
	DeleteFile(path2);
	m_pInstance->watcher.ClearInfoMap();
	ATLTRACE("cache loaded from disk successfully!\n");
	return;
error:
	fclose(pFile);
	DeleteFile(path2);
	m_pInstance->watcher.ClearInfoMap();
	if (m_pInstance)
	{
		m_pInstance->Stop();
		Sleep(100);
	}
	delete m_pInstance;
	m_pInstance = new CSVNStatusCache;
	ATLTRACE("cache not loaded from disk\n");
}