OSDN Git Service

initial TGitCache support added
authorMyagi <snowcoder@gmail.com>
Mon, 16 Feb 2009 18:46:51 +0000 (19:46 +0100)
committerFrank Li <lznuaa@gmail.com>
Mon, 16 Feb 2009 23:27:59 +0000 (07:27 +0800)
15 files changed:
src/Git/GitFolderStatus.cpp
src/Git/GitFolderStatus.h
src/Git/GitStatus.h
src/TGitCache/CacheInterface.h
src/TGitCache/CachedDirectory.cpp
src/TGitCache/CachedDirectory.h
src/TGitCache/FolderCrawler.cpp
src/TGitCache/StatusCacheEntry.cpp
src/TortoiseShell/ColumnProvider.cpp
src/TortoiseShell/IconOverlay.cpp
src/TortoiseShell/RemoteCacheLink.cpp
src/TortoiseShell/ShellCache.h
src/TortoiseShell/ShellExt.cpp
src/TortoiseShell/ShellExt.h
src/TortoiseShell/TortoiseShell.vcproj

index d56ec30..507070b 100644 (file)
@@ -429,7 +429,8 @@ BOOL GitFolderStatus::fillstatusmap(const struct wgFile_s *pFile, void *pUserDat
 \r
        s.author = Stat->authors.GetString(NULL);\r
        s.url = Stat->urls.GetString(NULL);\r
-//     s.rev = -1;\r
+       if (pFile->sha1)\r
+               s.rev = ConvertHashToRevnum(pFile->sha1);\r
        s.owner = Stat->owners.GetString(NULL);\r
 \r
        s.status = git_wc_status_none;\r
index d2febc5..646d7f3 100644 (file)
@@ -78,7 +78,7 @@ typedef struct FileStatusCacheEntry
        const char*                             url;            ///< points to a (possibly) shared value\r
        const char*                             owner;          ///< points to a (possible) lock owner\r
        bool                                    needslock;\r
-       //git_revnum_t                  rev;\r
+       git_revnum_t                    rev;\r
        int                                             askedcounter;\r
        //git_lock_t *                  lock;\r
        bool                                    tree_conflict;\r
index 2370184..aa21fa3 100644 (file)
@@ -50,6 +50,15 @@ typedef enum
 typedef CString git_revnum_t;\r
 typedef int git_error_t;\r
 \r
+typedef struct git_wc_entry_t\r
+{\r
+       // url in repository\r
+       const char *url;\r
+\r
+       TCHAR cmt_rev[41];\r
+} git_wc_entry_t;\r
+\r
+\r
 typedef struct git_wc_status2_t\r
 { \r
   /** The status of the entries text. */\r
@@ -57,6 +66,8 @@ typedef struct git_wc_status2_t
 \r
   /** The status of the entries properties. */\r
   git_wc_status_kind prop_status;\r
+\r
+  //git_wc_entry_t *entry;\r
 }git_wc_status2;\r
 \r
 #define MAX_STATUS_STRING_LENGTH               256\r
index 4a28d78..705e3d5 100644 (file)
@@ -72,7 +72,7 @@ struct TSVNCacheRequest
 struct TSVNCacheResponse\r
 {\r
        git_wc_status2_t m_status;\r
-//     svn_wc_entry_t m_entry;\r
+       git_wc_entry_t m_entry;\r
        git_node_kind_t m_kind;\r
        char m_url[INTERNET_MAX_URL_LENGTH+1];\r
        char m_owner[255];              ///< owner of the lock\r
index b77f0ad..3edd90b 100644 (file)
@@ -25,8 +25,8 @@
 \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
@@ -42,8 +42,8 @@ CCachedDirectory::CCachedDirectory(const CTGitPath& directoryPath)
        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
@@ -88,8 +88,8 @@ BOOL CCachedDirectory::SaveToDisk(FILE * pFile)
                        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
@@ -156,8 +156,8 @@ BOOL CCachedDirectory::LoadFromDisk(FILE * pFile)
                                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
@@ -195,43 +195,48 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
        {\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
@@ -245,6 +250,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                // 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
@@ -252,9 +258,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                // 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
@@ -276,7 +280,6 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                                CGitStatusCache::Instance().AddFolderForCrawling(it->first);\r
                                        }\r
                                }\r
-\r
                                return dirEntry->GetOwnStatus(bRecursive);\r
                        }\r
                }\r
@@ -341,14 +344,14 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                // 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
@@ -361,7 +364,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
 \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
@@ -395,9 +398,23 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                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
@@ -418,7 +435,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                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
@@ -428,7 +445,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                // 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
@@ -442,7 +459,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                                }\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
@@ -453,7 +470,7 @@ CStatusCacheEntry CCachedDirectory::GetStatusForMember(const CTGitPath& path, bo
                }\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
@@ -501,7 +518,7 @@ CCachedDirectory::AddEntry(const CTGitPath& path, const git_wc_status2_t* pGitSt
                {\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
@@ -525,6 +542,8 @@ CCachedDirectory::AddEntry(const CTGitPath& path, const git_wc_status2_t* pGitSt
                        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
@@ -543,6 +562,147 @@ CCachedDirectory::GetFullPathString(const CString& cacheKey)
        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
@@ -552,7 +712,6 @@ git_error_t * CCachedDirectory::GetStatusCallback(void *baton, const char *path,
                \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
@@ -665,11 +824,12 @@ git_error_t * CCachedDirectory::GetStatusCallback(void *baton, const char *path,
                        }\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
index 987c0d0..4d32ec0 100644 (file)
@@ -48,7 +48,8 @@ public:
        /// Get the current full status of this folder\r
        git_wc_status_kind GetCurrentFullStatus() {return m_currentFullStatus;}\r
 private:\r
-       static git_error_t* GetStatusCallback(void *baton, const char *path, git_wc_status2_t *status);\r
+//     static git_error_t* GetStatusCallback(void *baton, const char *path, git_wc_status2_t *status);\r
+       static BOOL GetStatusCallback(const struct wgFile_s *pFile, void *pUserData);\r
        void AddEntry(const CTGitPath& path, const git_wc_status2_t* pGitStatus, DWORD validuntil = 0);\r
        CString GetCacheKey(const CTGitPath& path);\r
        CString GetFullPathString(const CString& cacheKey);\r
@@ -76,10 +77,10 @@ private:
        typedef std::map<CTGitPath, git_wc_status_kind>  ChildDirStatus;\r
        ChildDirStatus m_childDirectories;\r
 \r
-       // The timestamp of the .SVN\entries file.  For an unversioned directory, this will be zero\r
-       __int64 m_entriesFileTime;\r
+       // The timestamp of the .git\index file.  For an unversioned directory, this will be zero\r
+       __int64 m_indexFileTime;\r
        // The timestamp of the .SVN\props dir.  For an unversioned directory, this will be zero\r
-       __int64 m_propsFileTime;\r
+//     __int64 m_propsFileTime;\r
        \r
        // The path of the directory with this object looks after\r
        CTGitPath       m_directoryPath;\r
index bab47be..ca92ee8 100644 (file)
@@ -240,23 +240,25 @@ void CFolderCrawler::WorkerThread()
                                // don't crawl paths that are excluded\r
                                if (!CGitStatusCache::Instance().IsPathAllowed(workingPath))\r
                                        continue;\r
-                               // check if the changed path is inside an .svn folder\r
-                               if ((workingPath.HasAdminDir()&&workingPath.IsDirectory())||workingPath.IsAdminDir())\r
+                               // check if the changed path is inside an .git folder\r
+                               if ((workingPath.HasAdminDir()&&workingPath.IsDirectory()) || workingPath.IsAdminDir())\r
                                {\r
-                                       // we don't crawl for paths changed in a tmp folder inside an .svn folder.\r
+                                       // we don't crawl for paths changed in a tmp folder inside an .git folder.\r
                                        // Because we also get notifications for those even if we just ask for the status!\r
                                        // And changes there don't affect the file status at all, so it's safe\r
                                        // to ignore notifications on those paths.\r
                                        if (workingPath.IsAdminDir())\r
                                        {\r
-                                               CString lowerpath = workingPath.GetWinPathString();\r
+                                               // TODO: add git specific filters here. is there really any change besides index file in .git\r
+                                               //       that is relevant for overlays?\r
+                                               /*CString lowerpath = workingPath.GetWinPathString();\r
                                                lowerpath.MakeLower();\r
                                                if (lowerpath.Find(_T("\\tmp\\"))>0)\r
                                                        continue;\r
                                                if (lowerpath.Find(_T("\\tmp")) == (lowerpath.GetLength()-4))\r
                                                        continue;\r
                                                if (lowerpath.Find(_T("\\log"))>0)\r
-                                                       continue;\r
+                                                       continue;*/\r
                                                // Here's a little problem:\r
                                                // the lock file is also created for fetching the status\r
                                                // and not just when committing.\r
index 7556094..5bedb4e 100644 (file)
@@ -61,7 +61,7 @@ bool CStatusCacheEntry::SaveToDisk(FILE * pFile)
        WRITEVALUETOFILE(m_lastWriteTime);\r
        WRITEVALUETOFILE(m_bSet);\r
        WRITEVALUETOFILE(m_bSVNEntryFieldSet);\r
-       WRITEVALUETOFILE(m_commitRevision);\r
+       CStringA srev(m_commitRevision); WRITESTRINGTOFILE(srev);\r
        WRITESTRINGTOFILE(m_sUrl);\r
        WRITESTRINGTOFILE(m_sOwner);\r
        WRITESTRINGTOFILE(m_sAuthor);\r
@@ -92,7 +92,19 @@ bool CStatusCacheEntry::LoadFromDisk(FILE * pFile)
                LOADVALUEFROMFILE(m_lastWriteTime);\r
                LOADVALUEFROMFILE(m_bSet);\r
                LOADVALUEFROMFILE(m_bSVNEntryFieldSet);\r
-               LOADVALUEFROMFILE(m_commitRevision);\r
+               LOADVALUEFROMFILE(value);\r
+               if (value != 0)\r
+               {\r
+                       CStringA s;\r
+                       if (fread(s.GetBuffer(value+1), sizeof(char), value, pFile)!=value)\r
+                       {\r
+                               s.ReleaseBuffer(0);\r
+                               m_commitRevision.Empty();\r
+                               return false;\r
+                       }\r
+                       s.ReleaseBuffer(value);\r
+                       m_commitRevision = s;\r
+               }\r
                LOADVALUEFROMFILE(value);\r
                if (value != 0)\r
                {\r
@@ -167,8 +179,7 @@ void CStatusCacheEntry::SetStatus(const git_wc_status2_t* pGitStatus)
                m_GitStatus = *pGitStatus;\r
 \r
                // Currently we don't deep-copy the whole entry value, but we do take a few members\r
-#if 0\r
-        if(pGitStatus->entry != NULL)\r
+/*        if(pGitStatus->entry != NULL)\r
                {\r
                        m_sUrl = pGitStatus->entry->url;\r
                        m_commitRevision = pGitStatus->entry->cmt_rev;\r
@@ -179,14 +190,13 @@ void CStatusCacheEntry::SetStatus(const git_wc_status2_t* pGitStatus)
                        if (pGitStatus->entry->present_props)\r
                                m_sPresentProps = pGitStatus->entry->present_props;\r
                }\r
-               else\r
+               else*/\r
                {\r
                        m_sUrl.Empty();\r
-                       m_commitRevision = 0;\r
+                       m_commitRevision = GIT_INVALID_REVNUM;\r
                        m_bSVNEntryFieldSet = false;\r
                }\r
-               m_GitStatus.entry = NULL;\r
-#endif\r
+//             m_GitStatus.entry = NULL;\r
        }\r
        m_discardAtTime = GetTickCount()+cachetimeout;\r
        m_bSet = true;\r
@@ -219,7 +229,7 @@ void CStatusCacheEntry::BuildCacheResponse(TSVNCacheResponse& response, DWORD& r
        if(m_bSVNEntryFieldSet)\r
        {\r
                response.m_status = m_GitStatus;\r
-//             response.m_entry.cmt_rev = m_commitRevision;\r
+               wcscpy_s(response.m_entry.cmt_rev, 41, m_commitRevision.GetString());\r
 \r
                // There is no point trying to set these pointers here, because this is not \r
                // the process which will be using the data.\r
index e0b7463..6140362 100644 (file)
@@ -24,7 +24,7 @@
 #include "UnicodeUtils.h"\r
 #include "GitStatus.h"\r
 #include "PathUtils.h"\r
-//#include "..\TSVNCache\CacheInterface.h"\r
+#include "..\TGitCache\CacheInterface.h"\r
 \r
 \r
 const static int ColumnFlags = SHCOLSTATE_TYPE_STR | SHCOLSTATE_ONBYDEFAULT;\r
@@ -342,15 +342,15 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
        case ShellCache::exe:\r
                {\r
                        SecureZeroMemory(&itemStatus, sizeof(itemStatus));\r
-                       if(m_remoteCacheLink.GetStatusFromRemoteCache(CTSVNPath(path), &itemStatus, true))\r
+                       if(m_remoteCacheLink.GetStatusFromRemoteCache(CTGitPath(path), &itemStatus, true))\r
                        {\r
-                               filestatus = SVNStatus::GetMoreImportant(itemStatus.m_status.text_status, itemStatus.m_status.prop_status);\r
+                               filestatus = GitStatus::GetMoreImportant(itemStatus.m_status.text_status, itemStatus.m_status.prop_status);\r
                        }\r
                        else\r
                        {\r
                                filestatus = git_wc_status_none;\r
                                columnauthor.clear();\r
-                               columnrev = 0;\r
+                               columnrev = GIT_INVALID_REVNUM;\r
                                itemurl.clear();\r
                                itemshorturl.clear();\r
                                owner.clear();\r
@@ -361,7 +361,7 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
        case ShellCache::dll:\r
        case ShellCache::dllFull:\r
                {\r
-                       status = m_CachedStatus.GetFullStatus(CTSVNPath(path), bIsDir, TRUE);\r
+                       status = m_CachedStatus.GetFullStatus(CTGitPath(path), bIsDir, TRUE);\r
                        filestatus = status->status;\r
                }\r
                break;\r
@@ -373,7 +373,7 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
                        else\r
                                filestatus = git_wc_status_none;\r
                        columnauthor.clear();\r
-                       columnrev = 0;\r
+                       columnrev = GIT_INVALID_REVNUM;\r
                        itemurl.clear();\r
                        itemshorturl.clear();\r
                        owner.clear();\r
@@ -423,7 +423,7 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
                        // Note: this will strip too much if such a folder is *below* the repository\r
                        // root - but it's called 'short url' and we're free to shorten it the way we\r
                        // like :)\r
-                       ptr = _tcsstr(urlComponents.lpszUrlPath, _T("/trunk"));\r
+                       /*ptr = _tcsstr(urlComponents.lpszUrlPath, _T("/trunk"));\r
                        if (ptr == NULL)\r
                                ptr = _tcsstr(urlComponents.lpszUrlPath, _T("\\trunk"));\r
                        if ((ptr == NULL)||((*(ptr+6) != 0)&&(*(ptr+6) != '/')&&(*(ptr+6) != '\\')))\r
@@ -442,7 +442,7 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
                        }\r
                        if (ptr)\r
                                itemshorturl = ptr;\r
-                       else\r
+                       else*/\r
                                itemshorturl = urlComponents.lpszUrlPath;\r
                }\r
                else \r
index 791ca32..bca63c6 100644 (file)
@@ -137,18 +137,16 @@ STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)
                {\r
                case ShellCache::exe:\r
                        {\r
-#if 0\r
                                TSVNCacheResponse itemStatus;\r
                                SecureZeroMemory(&itemStatus, sizeof(itemStatus));\r
                                if (m_remoteCacheLink.GetStatusFromRemoteCache(CTGitPath(pPath), &itemStatus, true))\r
                                {\r
                                        status = GitStatus::GetMoreImportant(itemStatus.m_status.text_status, itemStatus.m_status.prop_status);\r
-                                       if ((itemStatus.m_kind == git_node_file)&&(status == git_wc_status_normal)&&((itemStatus.m_needslock && itemStatus.m_owner[0]==0)||(itemStatus.m_readonly)))\r
+/*                                     if ((itemStatus.m_kind == git_node_file)&&(status == git_wc_status_normal)&&((itemStatus.m_needslock && itemStatus.m_owner[0]==0)||(itemStatus.m_readonly)))\r
                                                readonlyoverlay = true;\r
                                        if (itemStatus.m_owner[0]!=0)\r
-                                               lockedoverlay = true;\r
+                                               lockedoverlay = true;*/\r
                                }\r
-#endif\r
                        }\r
                        break;\r
                case ShellCache::dll:\r
@@ -207,6 +205,10 @@ STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)
                                        lockedoverlay = true;\r
                        }\r
 \r
+                       // index based version does not enumerate unversioned files, so default to unversioned\r
+                       if (g_ShellCache.GetCacheType() == ShellCache::dll\r
+                               && status == git_wc_status_none && g_ShellCache.HasSVNAdminDir(pPath, true))\r
+                               status = git_wc_status_unversioned;\r
                        break;\r
                default:\r
                case ShellCache::none:\r
@@ -244,11 +246,6 @@ STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)
        //if other handlers would return S_OK too (they're never called on my machine!)\r
        //So we return S_OK for ONLY ONE handler!\r
 \r
-       // TODO: not sure this should be here. if anywhere it should be in case 'dll' above\r
-       //       because if overlay type 'none' is selected we don't want this to change status to unversioned (which may have overlay)\r
-       if(g_ShellCache.HasSVNAdminDir(pPath, true) && status == git_wc_status_none)\r
-               status = git_wc_status_unversioned;\r
-\r
        switch (status)\r
        {\r
                // note: we can show other overlays if due to lack of enough free overlay\r
index a56d2e2..2e21500 100644 (file)
@@ -21,8 +21,6 @@
 #include "ShellExt.h"\r
 #include "..\TGitCache\CacheInterface.h"\r
 #include "TGitPath.h"\r
-#define GetCachePipeName() _T("HH")\r
-#define GetCacheCommandPipeName() _T("CC")\r
 \r
 CRemoteCacheLink::CRemoteCacheLink(void) \r
        : m_hPipe(INVALID_HANDLE_VALUE)\r
@@ -307,17 +305,17 @@ bool CRemoteCacheLink::GetStatusFromRemoteCache(const CTGitPath& Path, TSVNCache
 \r
        if (fSuccess)\r
        {\r
-/*             if(nBytesRead == sizeof(TSVNCacheResponse))\r
+               if(nBytesRead == sizeof(TSVNCacheResponse))\r
                {\r
                        // This is a full response - we need to fix-up some pointers\r
-                       pReturnedStatus->m_status.entry = &pReturnedStatus->m_entry;\r
-                       pReturnedStatus->m_entry.url = pReturnedStatus->m_url;\r
+//                     pReturnedStatus->m_status.entry = &pReturnedStatus->m_entry;\r
+//                     pReturnedStatus->m_entry.url = pReturnedStatus->m_url;\r
                }\r
                else\r
                {\r
-                       pReturnedStatus->m_status.entry = NULL;\r
+//                     pReturnedStatus->m_status.entry = NULL;\r
                }\r
-*/\r
+\r
                return true;\r
        }\r
        ClosePipe();\r
index b97284a..bfeb944 100644 (file)
@@ -153,11 +153,7 @@ public:
                        cachetypeticker = GetTickCount();\r
                        cachetype.read();\r
                }\r
-               //return CacheType(DWORD((cachetype)));\r
-               /*TEMP: until TGitCache done*/\r
-//             if(CGit::IsVista())\r
-//                     return none;\r
-               return CacheType(DWORD((cachetype))) == exe ? dll : CacheType(DWORD((cachetype)));\r
+               return CacheType(DWORD((cachetype)));\r
        }\r
        DWORD BlockStatus()\r
        {\r
index 7b89c23..60537b3 100644 (file)
@@ -282,7 +282,7 @@ UINT __stdcall CShellExt::CopyCallback(HWND /*hWnd*/, UINT wFunc, UINT /*wFlags*
        if (wFunc == FO_COPY)\r
                return IDYES;   // copying is not a problem for us\r
 \r
-//     m_remoteCacheLink.ReleaseLockForPath(CTSVNPath(pszSrcFile));\r
+       m_remoteCacheLink.ReleaseLockForPath(CTGitPath(pszSrcFile));\r
        // we could now wait a little bit to give the cache time to release the handles.\r
        // but the explorer/shell already retries any action for about two seconds\r
        // if it first fails. So if the cache hasn't released the handle yet, the explorer\r
index fe69901..e87abfb 100644 (file)
@@ -204,7 +204,7 @@ protected:
        stdstring itemshorturl;\r
        stdstring ignoredprops;\r
        stdstring owner;\r
-//     git_revnum_t columnrev;                 ///< holds the corresponding revision to the file/dir above\r
+       git_revnum_t columnrev;                 ///< holds the corresponding revision to the file/dir above\r
        git_wc_status_kind      filestatus;\r
        std::map<UINT, HBITMAP> bitmaps;\r
 \r
index 1805c66..e345be0 100644 (file)
                        Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"\r
                        >\r
                        <File\r
+                               RelativePath="..\TGitCache\CacheInterface.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="ColumnProvider.cpp"\r
                                >\r
                        </File>\r