bool CStatusCacheEntry::LoadFromDisk(FILE * pFile) { #define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) return false; try { unsigned int value = 0; LOADVALUEFROMFILE(value); if (value != CACHEVERION) return false; // not the correct version LOADVALUEFROMFILE(m_highestPriorityLocalStatus); LOADVALUEFROMFILE(m_lastWriteTime); LOADVALUEFROMFILE(m_bSet); LOADVALUEFROMFILE(m_kind); SecureZeroMemory(&m_GitStatus, sizeof(m_GitStatus)); LOADVALUEFROMFILE(m_GitStatus.prop_status); // LOADVALUEFROMFILE(m_GitStatus.repos_prop_status); // LOADVALUEFROMFILE(m_GitStatus.repos_text_status); LOADVALUEFROMFILE(m_GitStatus.text_status); LOADVALUEFROMFILE(m_GitStatus.assumeValid); LOADVALUEFROMFILE(m_GitStatus.skipWorktree); // m_GitStatus.entry = NULL; m_discardAtTime = GetTickCount()+cachetimeout; } catch ( CAtlException ) { return false; } return true; }
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"); }
BOOL CCachedDirectory::LoadFromDisk(FILE * pFile) { AutoLocker lock(m_critSec); #define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) return false; try { unsigned int value = 0; LOADVALUEFROMFILE(value); if (value != GIT_CACHE_VERSION) return false; // not the correct version int mapsize = 0; LOADVALUEFROMFILE(mapsize); for (int i=0; i<mapsize; ++i) { LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CString sKey; if (fread(sKey.GetBuffer(value+1), sizeof(TCHAR), value, pFile)!=value) { sKey.ReleaseBuffer(0); return false; } sKey.ReleaseBuffer(value); CStatusCacheEntry entry; if (!entry.LoadFromDisk(pFile)) return false; // only read non empty keys (just needed for transition from old TGit clients) if (!sKey.IsEmpty()) m_entryCache[sKey] = entry; } } LOADVALUEFROMFILE(mapsize); for (int i=0; i<mapsize; ++i) { LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CString sPath; if (fread(sPath.GetBuffer(value), sizeof(TCHAR), value, pFile)!=value) { sPath.ReleaseBuffer(0); return false; } sPath.ReleaseBuffer(value); git_wc_status_kind status; LOADVALUEFROMFILE(status); m_childDirectories[CTGitPath(sPath)] = status; } } LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CString sPath; if (fread(sPath.GetBuffer(value+1), sizeof(TCHAR), value, pFile)!=value) { sPath.ReleaseBuffer(0); return false; } sPath.ReleaseBuffer(value); // make sure paths do not end with backslash (just needed for transition from old TGit clients) if (sPath.GetLength() > 3 && sPath[sPath.GetLength() - 1] == _T('\\')) sPath.TrimRight(_T("\\")); m_directoryPath.SetFromWin(sPath); m_directoryPath.GetGitPathString(); // make sure git path string is set } if (!m_ownStatus.LoadFromDisk(pFile)) return false; LOADVALUEFROMFILE(m_currentFullStatus); LOADVALUEFROMFILE(m_mostImportantFileStatus); } catch ( CAtlException ) { return false; } return true; }
BOOL CCachedDirectory::LoadFromDisk(FILE * pFile) { AutoLocker lock(m_critSec); #define LOADVALUEFROMFILE(x) if (fread(&x, sizeof(x), 1, pFile)!=1) return false; try { unsigned int value = 0; LOADVALUEFROMFILE(value); if (value != CACHEDIRECTORYDISKVERSION) return false; // not the correct version int mapsize = 0; LOADVALUEFROMFILE(mapsize); for (int i=0; i<mapsize; ++i) { LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CStringA sKey; if (fread(sKey.GetBuffer(value+1), sizeof(char), value, pFile)!=value) { sKey.ReleaseBuffer(0); return false; } sKey.ReleaseBuffer(value); CStatusCacheEntry entry; if (!entry.LoadFromDisk(pFile)) return false; m_entryCache[sKey] = entry; } } LOADVALUEFROMFILE(mapsize); for (int i=0; i<mapsize; ++i) { LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CStringA sPath; if (fread(sPath.GetBuffer(value), sizeof(char), value, pFile)!=value) { sPath.ReleaseBuffer(0); return false; } sPath.ReleaseBuffer(value); svn_wc_status_kind status; LOADVALUEFROMFILE(status); m_childDirectories[sPath] = status; } } LOADVALUEFROMFILE(m_wcDbFileTime); LOADVALUEFROMFILE(value); if (value > MAX_PATH) return false; if (value) { CString sPath; if (fread(sPath.GetBuffer(value+1), sizeof(TCHAR), value, pFile)!=value) { sPath.ReleaseBuffer(0); return false; } sPath.ReleaseBuffer(value); m_directoryPath.SetFromWin(sPath); } if (!m_ownStatus.LoadFromDisk(pFile)) return false; LOADVALUEFROMFILE(m_currentFullStatus); LOADVALUEFROMFILE(m_mostImportantFileStatus); } catch ( CAtlException ) { return false; } return true; }