\r
CCachedDirectory::CCachedDirectory(void)\r
{\r
- m_entriesFileTime = 0;\r
- m_propsFileTime = 0;\r
+ m_indexFileTime = 0;\r
+// m_propsFileTime = 0;\r
m_currentStatusFetchingPathTicks = 0;\r
m_bCurrentFullStatusValid = false;\r
m_currentFullStatus = m_mostImportantFileStatus = git_wc_status_none;\r
ATLASSERT(directoryPath.IsDirectory() || !PathFileExists(directoryPath.GetWinPath()));\r
\r
m_directoryPath = directoryPath;\r
- m_entriesFileTime = 0;\r
- m_propsFileTime = 0;\r
+ m_indexFileTime = 0;\r
+// m_propsFileTime = 0;\r
m_currentStatusFetchingPathTicks = 0;\r
m_bCurrentFullStatusValid = false;\r
m_currentFullStatus = m_mostImportantFileStatus = git_wc_status_none;\r
WRITEVALUETOFILE(status);\r
}\r
}\r
- WRITEVALUETOFILE(m_entriesFileTime);\r
- WRITEVALUETOFILE(m_propsFileTime);\r
+ WRITEVALUETOFILE(m_indexFileTime);\r
+// WRITEVALUETOFILE(m_propsFileTime);\r
value = m_directoryPath.GetWinPathString().GetLength();\r
WRITEVALUETOFILE(value);\r
if (value)\r
m_childDirectories[CTGitPath(sPath)] = status;\r
}\r
}\r
- LOADVALUEFROMFILE(m_entriesFileTime);\r
- LOADVALUEFROMFILE(m_propsFileTime);\r
+ LOADVALUEFROMFILE(m_indexFileTime);\r
+// LOADVALUEFROMFILE(m_propsFileTime);\r
LOADVALUEFROMFILE(value);\r
if (value > MAX_PATH)\r
return false;\r
{\r
bRequestForSelf = true;\r
}\r
-\r
+//OutputDebugStringA("GetStatusForMember: ");OutputDebugStringW(path.GetWinPathString());OutputDebugStringA("\r\n");\r
// In all most circumstances, we ask for the status of a member of this directory.\r
ATLASSERT(m_directoryPath.IsEquivalentToWithoutCase(path.GetContainingDirectory()) || bRequestForSelf);\r
\r
- // Check if the entries file has been changed\r
- CTGitPath entriesFilePath(m_directoryPath);\r
- CTGitPath propsDirPath(m_directoryPath);\r
+ CString sProjectRoot;\r
+ const BOOL bIsVersionedPath = m_directoryPath.HasAdminDir(&sProjectRoot);\r
+\r
+ // Check if the index file has been changed\r
+ CTGitPath indexFilePath(bIsVersionedPath ? sProjectRoot : m_directoryPath);\r
+// CTGitPath propsDirPath(m_directoryPath);\r
if (g_GitAdminDir.IsVSNETHackActive())\r
{\r
- entriesFilePath.AppendPathString(g_GitAdminDir.GetVSNETAdminDirName() + _T("\\entries"));\r
- propsDirPath.AppendPathString(g_GitAdminDir.GetVSNETAdminDirName() + _T("\\dir-props"));\r
+ indexFilePath.AppendPathString(g_GitAdminDir.GetVSNETAdminDirName() + _T("\\index"));\r
+// propsDirPath.AppendPathString(g_GitAdminDir.GetVSNETAdminDirName() + _T("\\dir-props"));\r
}\r
else\r
{\r
- entriesFilePath.AppendPathString(g_GitAdminDir.GetAdminDirName() + _T("\\entries"));\r
- propsDirPath.AppendPathString(g_GitAdminDir.GetAdminDirName() + _T("\\dir-props"));\r
+ indexFilePath.AppendPathString(g_GitAdminDir.GetAdminDirName() + _T("\\index"));\r
+// propsDirPath.AppendPathString(g_GitAdminDir.GetAdminDirName() + _T("\\dir-props"));\r
}\r
- if ( (m_entriesFileTime == entriesFilePath.GetLastWriteTime()) && ((entriesFilePath.GetLastWriteTime() == 0) || (m_propsFileTime == propsDirPath.GetLastWriteTime())) )\r
+ if ( (m_indexFileTime == indexFilePath.GetLastWriteTime()) /*&& ((indexFilePath.GetLastWriteTime() == 0) || (m_propsFileTime == propsDirPath.GetLastWriteTime()))*/ )\r
{\r
- m_entriesFileTime = entriesFilePath.GetLastWriteTime();\r
- if (m_entriesFileTime)\r
- m_propsFileTime = propsDirPath.GetLastWriteTime();\r
+// m_indexFileTime = indexFilePath.GetLastWriteTime();\r
+// if (m_indexFileTime)\r
+// m_propsFileTime = propsDirPath.GetLastWriteTime();\r
\r
- if(m_entriesFileTime == 0)\r
+ //if(m_indexFileTime == 0)\r
+ // a newly created project (without commits) has no index file but we still want it to count as versioned\r
+ if(m_indexFileTime == 0 && !bIsVersionedPath)\r
{\r
// We are a folder which is not in a working copy\r
bThisDirectoryIsUnversioned = true;\r
m_ownStatus.SetStatus(NULL);\r
\r
- // If a user removes the .svn directory, we get here with m_entryCache\r
+ // If a user removes the .git directory, we get here with m_entryCache\r
// not being empty, but still us being unversioned\r
if (!m_entryCache.empty())\r
{\r
m_entryCache.clear();\r
}\r
ATLASSERT(m_entryCache.empty());\r
- \r
+\r
// However, a member *DIRECTORY* might be the top of WC\r
// so we need to ask them to get their own status\r
if(!path.IsDirectory())\r
// So mark it for crawling, and let the crawler remove it\r
// later\r
CGitStatusCache::Instance().AddFolderForCrawling(path.GetContainingDirectory());\r
+\r
return CStatusCacheEntry();\r
}\r
else\r
// If we're in the special case of a directory being asked for its own status\r
// and this directory is unversioned, then we should just return that here\r
if(bRequestForSelf)\r
- {\r
return CStatusCacheEntry();\r
- }\r
}\r
}\r
\r
CGitStatusCache::Instance().AddFolderForCrawling(it->first);\r
}\r
}\r
-\r
return dirEntry->GetOwnStatus(bRecursive);\r
}\r
}\r
// we already have (to save time and make the explorer\r
// more responsive in stress conditions).\r
// We leave the refreshing to the crawler.\r
- if ((!bFetch)&&(m_entriesFileTime))\r
+ if ((!bFetch)&&(m_indexFileTime))\r
{\r
CGitStatusCache::Instance().AddFolderForCrawling(path.GetDirectory());\r
return CStatusCacheEntry();\r
}\r
AutoLocker lock(m_critSec);\r
- m_entriesFileTime = entriesFilePath.GetLastWriteTime();\r
- m_propsFileTime = propsDirPath.GetLastWriteTime();\r
+ m_indexFileTime = indexFilePath.GetLastWriteTime();\r
+// m_propsFileTime = propsDirPath.GetLastWriteTime();\r
m_entryCache.clear();\r
strCacheKey = GetCacheKey(path);\r
}\r
\r
if (g_GitAdminDir.IsAdminDirPath(path.GetWinPathString()))\r
{\r
- // We're being asked for the status of an .SVN directory\r
+ // We're being asked for the status of an .git directory\r
// It's not worth asking for this\r
return CStatusCacheEntry();\r
}\r
m_currentStatusFetchingPath = m_directoryPath;\r
m_currentStatusFetchingPathTicks = GetTickCount();\r
}\r
- ATLTRACE(_T("svn_cli_stat for '%s' (req %s)\n"), m_directoryPath.GetWinPath(), path.GetWinPath());\r
+ ATLTRACE(_T("git_enum_files for '%s' (req %s)\n"), m_directoryPath.GetWinPath(), path.GetWinPath());\r
\r
- BOOL pErr = 0;//!wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath|WGEFF_DirStatusAll, &fillstatusmap, this);\r
+ CString sProjectRoot;\r
+ m_directoryPath.HasAdminDir(&sProjectRoot);\r
+ ATLASSERT( !m_directoryPath.IsEmpty() );\r
+\r
+ LPCSTR lpszSubPath = NULL;\r
+ CStringA sSubPath;\r
+ CString s = m_directoryPath.GetDirectory().GetWinPathString();\r
+ if (s.GetLength() > sProjectRoot.GetLength())\r
+ {\r
+ sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
+ lpszSubPath = sSubPath;\r
+ }\r
+//MessageBoxA(NULL, CStringA(sProjectRoot), sSubPath, MB_OK);\r
+//OutputDebugStringA("###");OutputDebugStringW(sProjectRoot);OutputDebugStringA(" - ");OutputDebugStringA(sSubPath);OutputDebugStringA("\r\n");\r
+ BOOL pErr = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath, &GetStatusCallback, this);\r
\r
/*git_error_t* pErr = svn_client_status4 (\r
NULL,\r
AutoLocker pathlock(m_critSecPath);\r
m_currentStatusFetchingPath.Reset();\r
}\r
- ATLTRACE(_T("svn_cli_stat finished for '%s'\n"), m_directoryPath.GetWinPath(), path.GetWinPath());\r
+ ATLTRACE(_T("git_enum_files finished for '%s'\n"), m_directoryPath.GetWinPath(), path.GetWinPath());\r
if(pErr)\r
{\r
// Handle an error\r
// If we allow ourselves to fall on through, then folders will be asked\r
// for their own status, and will set themselves as unversioned, for the \r
// benefit of future requests\r
-// ATLTRACE("svn_cli_stat err: '%s'\n", pErr->message);\r
+// ATLTRACE("git_enum_files err: '%s'\n", pErr->message);\r
// svn_error_clear(pErr);\r
// No assert here! Since we _can_ get here, an assertion is not an option!\r
// Reasons to get here: \r
}\r
else\r
{\r
- ATLTRACE("svn_cli_stat error, assume none status\n");\r
+ ATLTRACE("git_enum_files error, assume none status\n");\r
// Since we only assume a none status here due to svn_client_status()\r
// returning an error, make sure that this status times out soon.\r
CGitStatusCache::Instance().m_folderCrawler.BlockPath(m_directoryPath, 2000);\r
}\r
else\r
{\r
- ATLTRACE("Skipped SVN status for unversioned folder\n");\r
+ ATLTRACE("Skipped git status for unversioned folder\n");\r
}\r
}\r
// Now that we've refreshed our SVN status, we can see if it's \r
{\r
if ((childDir->GetCurrentFullStatus() != git_wc_status_missing)||(pGitStatus==NULL)||(pGitStatus->text_status != git_wc_status_unversioned))\r
childDir->m_ownStatus.SetStatus(pGitStatus);\r
-// childDir->m_ownStatus.SetKind(svn_node_dir);\r
+ childDir->m_ownStatus.SetKind(git_node_dir);\r
}\r
}\r
else\r
entry_it = m_entryCache.insert(entry_it, std::make_pair(cachekey, CStatusCacheEntry()));\r
}\r
entry_it->second = CStatusCacheEntry(pGitStatus, path.GetLastWriteTime(), path.IsReadOnly(), validuntil);\r
+ // TEMP(?): git status doesn't not have "entry" that contains node type, so manually set as file\r
+ entry_it->second.SetKind(git_node_file);\r
}\r
}\r
\r
return m_directoryPath.GetWinPathString() + _T("\\") + cacheKey;\r
}\r
\r
+BOOL CCachedDirectory::GetStatusCallback(const struct wgFile_s *pFile, void *pUserData)\r
+{\r
+ CCachedDirectory* pThis = (CCachedDirectory*)pUserData;\r
+\r
+ const char *path = pFile->sFileName;\r
+\r
+ if (path == NULL)\r
+ return FALSE;\r
+\r
+ git_wc_status2_t _status;\r
+ git_wc_status2_t *status = &_status;\r
+\r
+ if ((pFile->nFlags & WGFF_Directory) && pFile->nStatus == WGFS_Unknown)\r
+ status->prop_status = status->text_status = git_wc_status_incomplete;\r
+ else\r
+ status->prop_status = status->text_status = GitStatusFromWingit(pFile->nStatus);\r
+//if (pFile->nStatus > WGFS_Normal) {CStringA s; s.Format("==>%s %d\r\n",pFile->sFileName,pFile->nStatus); OutputDebugStringA(s);}\r
+ CTGitPath svnPath;\r
+\r
+// if(status->entry)\r
+ {\r
+ //if ((status->text_status != git_wc_status_none)&&(status->text_status != git_wc_status_missing))\r
+ svnPath.SetFromGit(path, pFile->nFlags & WGFF_Directory);\r
+ /*else\r
+ svnPath.SetFromGit(path);*/\r
+\r
+ if (pFile->nFlags & WGFF_Directory)\r
+ {\r
+ if ( !svnPath.IsEquivalentToWithoutCase(pThis->m_directoryPath) )\r
+ {\r
+ if (pThis->m_bRecursive)\r
+ {\r
+ // Add any versioned directory, which is not our 'self' entry, to the list for having its status updated\r
+//OutputDebugStringA("AddFolderCrawl: ");OutputDebugStringW(svnPath.GetWinPathString());OutputDebugStringA("\r\n");\r
+ CGitStatusCache::Instance().AddFolderForCrawling(svnPath);\r
+ }\r
+\r
+ // Make sure we know about this child directory\r
+ // This initial status value is likely to be overwritten from below at some point\r
+ git_wc_status_kind s = GitStatus::GetMoreImportant(status->text_status, status->prop_status);\r
+ CCachedDirectory * cdir = CGitStatusCache::Instance().GetDirectoryCacheEntryNoCreate(svnPath);\r
+ if (cdir)\r
+ {\r
+ // This child directory is already in our cache!\r
+ // So ask this dir about its recursive status\r
+ git_wc_status_kind st = GitStatus::GetMoreImportant(s, cdir->GetCurrentFullStatus());\r
+ AutoLocker lock(pThis->m_critSec);\r
+ pThis->m_childDirectories[svnPath] = st;\r
+ }\r
+ else\r
+ {\r
+ // the child directory is not in the cache. Create a new entry for it in the cache which is\r
+ // initially 'unversioned'. But we added that directory to the crawling list above, which\r
+ // means the cache will be updated soon.\r
+ CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);\r
+ AutoLocker lock(pThis->m_critSec);\r
+ pThis->m_childDirectories[svnPath] = s;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ // Keep track of the most important status of all the files in this directory\r
+ // Don't include subdirectories in this figure, because they need to provide their \r
+ // own 'most important' value\r
+ pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, status->text_status);\r
+ pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, status->prop_status);\r
+ if (((status->text_status == git_wc_status_unversioned)||(status->text_status == git_wc_status_none))\r
+ &&(CGitStatusCache::Instance().IsUnversionedAsModified()))\r
+ {\r
+ // treat unversioned files as modified\r
+ if (pThis->m_mostImportantFileStatus != git_wc_status_added)\r
+ pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, git_wc_status_modified);\r
+ }\r
+ }\r
+ }\r
+#if 0\r
+ else\r
+ {\r
+ svnPath.SetFromGit(path);\r
+ // Subversion returns no 'entry' field for versioned folders if they're\r
+ // part of another working copy (nested layouts).\r
+ // So we have to make sure that such an 'unversioned' folder really\r
+ // is unversioned.\r
+ if (((status->text_status == git_wc_status_unversioned)||(status->text_status == git_wc_status_missing))&&(!svnPath.IsEquivalentToWithoutCase(pThis->m_directoryPath))&&(svnPath.IsDirectory()))\r
+ {\r
+ if (svnPath.HasAdminDir())\r
+ {\r
+ CGitStatusCache::Instance().AddFolderForCrawling(svnPath);\r
+ // Mark the directory as 'versioned' (status 'normal' for now).\r
+ // This initial value will be overwritten from below some time later\r
+ {\r
+ AutoLocker lock(pThis->m_critSec);\r
+ pThis->m_childDirectories[svnPath] = git_wc_status_normal;\r
+ }\r
+ // Make sure the entry is also in the cache\r
+ CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);\r
+ // also mark the status in the status object as normal\r
+ status->text_status = git_wc_status_normal;\r
+ }\r
+ }\r
+ else if (status->text_status == git_wc_status_external)\r
+ {\r
+ CGitStatusCache::Instance().AddFolderForCrawling(svnPath);\r
+ // Mark the directory as 'versioned' (status 'normal' for now).\r
+ // This initial value will be overwritten from below some time later\r
+ {\r
+ AutoLocker lock(pThis->m_critSec);\r
+ pThis->m_childDirectories[svnPath] = git_wc_status_normal;\r
+ }\r
+ // we have added a directory to the child-directory list of this\r
+ // directory. We now must make sure that this directory also has\r
+ // an entry in the cache.\r
+ CGitStatusCache::Instance().GetDirectoryCacheEntry(svnPath);\r
+ // also mark the status in the status object as normal\r
+ status->text_status = git_wc_status_normal;\r
+ }\r
+ else\r
+ {\r
+ if (svnPath.IsDirectory())\r
+ {\r
+ AutoLocker lock(pThis->m_critSec);\r
+ pThis->m_childDirectories[svnPath] = GitStatus::GetMoreImportant(status->text_status, status->prop_status);\r
+ }\r
+ else if ((CGitStatusCache::Instance().IsUnversionedAsModified())&&(status->text_status != git_wc_status_missing))\r
+ {\r
+ // make this unversioned item change the most important status of this\r
+ // folder to modified if it doesn't already have another status\r
+ if (pThis->m_mostImportantFileStatus != git_wc_status_added)\r
+ pThis->m_mostImportantFileStatus = GitStatus::GetMoreImportant(pThis->m_mostImportantFileStatus, git_wc_status_modified);\r
+ }\r
+ }\r
+ }\r
+#endif\r
+\r
+ pThis->AddEntry(svnPath, status);\r
+\r
+ return FALSE;\r
+}\r
+\r
+#if 0\r
git_error_t * CCachedDirectory::GetStatusCallback(void *baton, const char *path, git_wc_status2_t *status)\r
{\r
CCachedDirectory* pThis = (CCachedDirectory*)baton;\r
\r
CTGitPath svnPath;\r
\r
-#if 0\r
if(status->entry)\r
{\r
if ((status->text_status != git_wc_status_none)&&(status->text_status != git_wc_status_missing))\r
}\r
}\r
}\r
-#endif\r
+\r
pThis->AddEntry(svnPath, status);\r
\r
return 0;\r
}\r
+#endif\r
\r
bool \r
CCachedDirectory::IsOwnStatusValid() const\r