void CGitStatusCache::Create() { ATLASSERT(m_pInstance == NULL); m_pInstance = new CGitStatusCache; 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("\\TGitCache")); if (!PathIsDirectory(path)) { if (CreateDirectory(path, NULL)==0) goto error; } _tcscat_s(path, MAX_PATH, _T("\\cache")); // 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 != 2) { 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); CCachedDirectory * cacheddir = new CCachedDirectory(); if (cacheddir == NULL) goto error; if (!cacheddir->LoadFromDisk(pFile)) goto error; CTGitPath KeyPath = CTGitPath(sKey); if (m_pInstance->IsPathAllowed(KeyPath)) { m_pInstance->m_directoryCache[KeyPath] = cacheddir; // only add the path to the watch list if it is versioned if ((cacheddir->GetCurrentFullStatus() != git_wc_status_unversioned)&&(cacheddir->GetCurrentFullStatus() != git_wc_status_none)) m_pInstance->watcher.AddPath(KeyPath, false); // 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: if (pFile) fclose(pFile); DeleteFile(path2); m_pInstance->watcher.ClearInfoMap(); Destroy(); m_pInstance = new CGitStatusCache; ATLTRACE("cache not loaded from disk\n"); }
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"); }