OSDN Git Service

"dual" file status support added (option for index file based or igit.exe based)
authorMyagi <snowcoder@gmail.com>
Fri, 13 Feb 2009 01:11:15 +0000 (02:11 +0100)
committerFrank Li <lznuaa@gmail.com>
Fri, 13 Feb 2009 14:22:58 +0000 (22:22 +0800)
src/Git/GitFolderStatus.cpp
src/Git/GitFolderStatus.h
src/Git/GitStatus.cpp
src/TGitCache/TSVNCache.vcproj
src/TortoiseGitBlame/TortoiseGitBlame.vcproj
src/TortoiseShell/ColumnProvider.cpp
src/TortoiseShell/ContextMenu.cpp
src/TortoiseShell/IconOverlay.cpp
src/TortoiseShell/ShellCache.h

index 17f1b3f..d56ec30 100644 (file)
@@ -116,7 +116,7 @@ const FileStatusCacheEntry * GitFolderStatus::BuildCache(const CTGitPath& filepa
 //     apr_hash_t *                            statushash;\r
 //     apr_pool_t *                            pool;\r
        //git_error_t *                         err = NULL; // If svn_client_status comes out through catch(...), err would else be unassigned\r
-       BOOL err = FALSE;\r
+       git_error_t err = 0;\r
 \r
        //dont' build the cache if an instance of TortoiseProc is running\r
        //since this could interfere with svn commands running (concurrent\r
@@ -231,40 +231,53 @@ const FileStatusCacheEntry * GitFolderStatus::BuildCache(const CTGitPath& filepa
 //     rev.kind = git_opt_revision_unspecified;\r
        try\r
        {\r
-               // extract the sub-path (relative to project root)\r
-//MessageBox(NULL, filepath.GetDirectory().GetWinPathString(), sProjectRoot, MB_OK);\r
-//             LPCSTR lpszSubPath = NULL;\r
-               CString sSubPath;\r
-               CString s = filepath.GetWinPathString();\r
-               if (s.GetLength() > sProjectRoot.GetLength())\r
+               if (g_ShellCache.GetCacheType() == ShellCache::dll)\r
                {\r
-                       sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/);\r
-//                     lpszSubPath = sSubPath;\r
+                       // gitindex.h based status\r
+\r
+                       // extract the sub-path (relative to project root)\r
+                       CString sSubPath;\r
+                       CString s = filepath.GetWinPathString();\r
+                       if (s.GetLength() > sProjectRoot.GetLength())\r
+                       {\r
+                                       sSubPath = s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/);\r
+                       }\r
+\r
+                       git_wc_status_kind status;\r
+\r
+                       err = g_IndexFileMap.GetFileStatus((CString&)sProjectRoot,sSubPath,&status,true,true,fillstatusmap_idx,this);\r
                }\r
+               else\r
+               {\r
+                       // extract the sub-path (relative to project root)\r
+//MessageBox(NULL, filepath.GetDirectory().GetWinPathString(), sProjectRoot, MB_OK);\r
+                       LPCSTR lpszSubPath = NULL;\r
+                       CStringA sSubPath;\r
+                       CString s = filepath.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
 \r
 //if (lpszSubPath) MessageBoxA(NULL, lpszSubPath, "BuildCache", MB_OK);\r
 //MessageBoxA(NULL, CStringA(sProjectRoot), sSubPath, MB_OK);\r
-               //err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath|WGEFF_DirStatusAll, &fillstatusmap, this);\r
-               //CTGitPath path;\r
-               //path.SetFromWin(sSubPath);\r
-               git_wc_status_kind status;\r
-\r
-               err = g_IndexFileMap.GetFileStatus((CString&)sProjectRoot,sSubPath,&status,true,true,fillstatusmap,this);\r
-               \r
-               //err = g_IndexFileMap.GetFileStatus(sProjectRoot,&path,\r
-               /*err = svn_client_status4 (&youngest,\r
-                       filepath.GetDirectory().GetSVNApiPath(pool),\r
-                       &rev,\r
-                       fillstatusmap,\r
-                       this,\r
-                       svn_depth_immediates,           //depth\r
-                       TRUE,           //getall\r
-                       FALSE,          //update\r
-                       TRUE,           //noignore\r
-                       FALSE,          //ignore externals\r
-                       NULL,\r
-                       localctx,\r
-                       pool);*/\r
+                       err = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, WGEFF_NoRecurse|WGEFF_FullPath|WGEFF_DirStatusAll, &fillstatusmap, this);\r
+\r
+                       /*err = svn_client_status4 (&youngest,\r
+                               filepath.GetDirectory().GetSVNApiPath(pool),\r
+                               &rev,\r
+                               fillstatusmap,\r
+                               this,\r
+                               svn_depth_immediates,           //depth\r
+                               TRUE,           //getall\r
+                               FALSE,          //update\r
+                               TRUE,           //noignore\r
+                               FALSE,          //ignore externals\r
+                               NULL,\r
+                               localctx,\r
+                               pool);*/\r
+               }\r
        }\r
        catch ( ... )\r
        {\r
@@ -405,7 +418,47 @@ const FileStatusCacheEntry * GitFolderStatus::GetCachedItem(const CTGitPath& fil
        return NULL;\r
 }\r
 \r
-void GitFolderStatus::fillstatusmap(CString &path,git_wc_status_kind status,void *pUserData)\r
+BOOL GitFolderStatus::fillstatusmap(const struct wgFile_s *pFile, void *pUserData)\r
+{\r
+       GitFolderStatus *Stat = (GitFolderStatus*)pUserData;\r
+\r
+       FileStatusMap &cache = Stat->m_cache;\r
+       FileStatusCacheEntry s;\r
+       s.needslock = false;\r
+       s.tree_conflict = false;\r
+\r
+       s.author = Stat->authors.GetString(NULL);\r
+       s.url = Stat->urls.GetString(NULL);\r
+//     s.rev = -1;\r
+       s.owner = Stat->owners.GetString(NULL);\r
+\r
+       s.status = git_wc_status_none;\r
+\r
+       //s.status = GitStatus::GetMoreImportant(s.status, status->text_status);\r
+       //s.status = GitStatus::GetMoreImportant(s.status, status->prop_status);\r
+       s.status = GitStatusFromWingit(pFile->nStatus);\r
+\r
+       // TODO ?: s.blaha = pFile->nStage\r
+\r
+       //s.lock = status->repos_lock;\r
+       //s.tree_conflict = (status->tree_conflict != NULL);\r
+\r
+       s.askedcounter = GITFOLDERSTATUS_CACHETIMES;\r
+       stdstring str;\r
+       if (pFile->sFileName)\r
+       {\r
+               str = CUnicodeUtils::StdGetUnicode(pFile->sFileName);\r
+               std::replace(str.begin(), str.end(), '/', '\\');\r
+//MessageBox(NULL, str.c_str(), _T(""), MB_OK);\r
+       }\r
+       else\r
+               str = _T(" ");\r
+       cache[str] = s;\r
+\r
+       return FALSE;\r
+}\r
+\r
+void GitFolderStatus::fillstatusmap_idx(CString &path,git_wc_status_kind status,void *pUserData)\r
 {\r
        GitFolderStatus *Stat = (GitFolderStatus*)pUserData;\r
 \r
index dba9f4f..d2febc5 100644 (file)
@@ -117,7 +117,8 @@ private:
        DWORD                           GetTimeoutValue();\r
        //static git_error_t*   fillstatusmap (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);\r
        //static git_error_t*   findfolderstatus (void *baton, const char *path, git_wc_status2_t *status, apr_pool_t *pool);\r
-       static void                     fillstatusmap(CString &path,git_wc_status_kind status,void *pdata);\r
+       static BOOL                     fillstatusmap(const struct wgFile_s *pFile, void *pUserData);\r
+       static void                     fillstatusmap_idx(CString &path,git_wc_status_kind status,void *pdata);\r
 \r
        static CTGitPath        folderpath;\r
        void                            ClearCache();\r
index 9aeca87..c2032a8 100644 (file)
 //\r
 \r
 #include "stdafx.h"\r
+#ifdef _TORTOISESHELL\r
+#include "ShellExt.h"\r
+#else\r
+#include "registry.h"\r
+#endif\r
 //#include "resource.h"\r
 #include "..\TortoiseShell\resource.h"\r
 //#include "git_config.h"\r
@@ -217,35 +222,52 @@ git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t de
 \r
        const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source\r
 \r
-       //LPCSTR lpszSubPath = NULL;\r
-       CString sSubPath;\r
-       CString s = path.GetWinPathString();\r
-       if (s.GetLength() > sProjectRoot.GetLength())\r
+#ifdef _TORTOISESHELL\r
+       if (g_ShellCache.GetCacheType() == ShellCache::dll)\r
+#else\r
+       if ((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? 2 : 1) == 2)\r
+#endif\r
        {\r
-               sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
-       //      lpszSubPath = sSubPath;\r
+               // gitindex.h based status\r
+\r
+               CString sSubPath;\r
+               CString s = path.GetWinPathString();\r
+               if (s.GetLength() > sProjectRoot.GetLength())\r
+               {\r
+                       sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
+               }\r
+\r
+               err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&statuskind);\r
        }\r
+       else\r
+       {\r
+               LPCSTR lpszSubPath = NULL;\r
+               CStringA sSubPath;\r
+               CString s = path.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
 \r
 #if 1\r
-       // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
-       //UINT nFlags = WGEFF_SingleFile;\r
-       //if (!bIsRecursive)\r
-       //      nFlags |= WGEFF_NoRecurse;\r
-       //if (!lpszSubPath)\r
-               // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
-       //      nFlags |= WGEFF_EmptyAsNormal;\r
+               // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
+               UINT nFlags = WGEFF_SingleFile;\r
+               if (!bIsRecursive)\r
+                       nFlags |= WGEFF_NoRecurse;\r
+               if (!lpszSubPath)\r
+                       // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
+                       nFlags |= WGEFF_EmptyAsNormal;\r
 #else\r
-       // enumerate all files, recursively if requested\r
-       UINT nFlags = 0;\r
-       if (!bIsRecursive)\r
-               nFlags |= WGEFF_NoRecurse;\r
+               // enumerate all files, recursively if requested\r
+               UINT nFlags = 0;\r
+               if (!bIsRecursive)\r
+                       nFlags |= WGEFF_NoRecurse;\r
 #endif\r
 \r
-       //err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
-       \r
-       err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&statuskind);\r
+               err = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
 \r
-       /*err = git_client_status4 (&youngest,\r
+               /*err = git_client_status4 (&youngest,\r
                                                        path.GetSVNApiPath(pool),\r
                                                        &rev,\r
                                                        getallstatus,\r
@@ -258,6 +280,7 @@ git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t de
                                                        NULL,\r
                                                        ctx,\r
                                                        pool);*/\r
+       }\r
 \r
        // Error present\r
        if (err != NULL)\r
@@ -348,30 +371,48 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
 //     hashbaton.exthash = exthash;\r
        hashbaton.pThis = this;\r
 \r
-       //LPCSTR lpszSubPath = NULL;\r
-       CString sSubPath;\r
-       CString s = path.GetWinPathString();\r
-       if (s.GetLength() > sProjectRoot.GetLength())\r
+#ifdef _TORTOISESHELL\r
+       if (g_ShellCache.GetCacheType() == ShellCache::dll)\r
+#else\r
+       if ((DWORD)CRegStdWORD(_T("Software\\TortoiseGit\\CacheType"), GetSystemMetrics(SM_REMOTESESSION) ? 2 : 1) == 2)\r
+#endif\r
        {\r
-               sSubPath = CString(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
-       //      lpszSubPath = sSubPath;\r
+               // gitindex.h based status\r
+\r
+               CString sSubPath;\r
+               CString s = path.GetWinPathString();\r
+               if (s.GetLength() > sProjectRoot.GetLength())\r
+               {\r
+                       sSubPath = CString(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
+               }\r
+\r
+               m_status.prop_status = m_status.text_status = git_wc_status_none;\r
+\r
+               m_err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&m_status.text_status);\r
        }\r
+       else\r
+       {\r
+               LPCSTR lpszSubPath = NULL;\r
+               CStringA sSubPath;\r
+               CString s = path.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
 \r
-       \r
-       // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
-       //UINT nFlags = WGEFF_SingleFile | WGEFF_NoRecurse;\r
-       //if (!lpszSubPath)\r
-       //      // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
-       //      nFlags |= WGEFF_EmptyAsNormal;\r
+               // when recursion enabled, let wingit determine the recursive status for folders instead of enumerating all files here\r
+               UINT nFlags = WGEFF_SingleFile | WGEFF_NoRecurse;\r
+               if (!lpszSubPath)\r
+                       // report root dir as normal (otherwise it could be considered git_wc_status_unversioned, which would be wrong?)\r
+                       nFlags |= WGEFF_EmptyAsNormal;\r
 \r
-       m_status.prop_status = m_status.text_status = git_wc_status_none;\r
+               m_status.prop_status = m_status.text_status = git_wc_status_none;\r
 \r
-       // NOTE: currently wgEnumFiles_safe_safe_safe will not enumerate file if it isn't versioned (so status will be git_wc_status_none)\r
-       //m_err = !wgEnumFiles_safe(CStringA(sProjectRoot), lpszSubPath, nFlags, &getstatus, &m_status);\r
+               // NOTE: currently wgEnumFiles will not enumerate file if it isn't versioned (so status will be git_wc_status_none)\r
+               m_err = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, nFlags, &getstatus, &m_status);\r
 \r
-       m_err = g_IndexFileMap.GetFileStatus(sProjectRoot,sSubPath,&m_status.text_status);\r
-       \r
-       /*m_err = git_client_status4 (&youngest,\r
+               /*m_err = git_client_status4 (&youngest,\r
                                                        path.GetGitApiPath(m_pool),\r
                                                        &rev,\r
                                                        getstatushash,\r
@@ -384,7 +425,7 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
                                                        NULL,\r
                                                        ctx,\r
                                                        m_pool);*/\r
-\r
+       }\r
 \r
        // Error present if function is not under version control\r
        if (m_err) /*|| (apr_hash_count(statushash) == 0)*/\r
@@ -407,9 +448,9 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
 \r
        if (update)\r
        {\r
-               //const BYTE *sha1 = wgGetRevisionID_safe(CStringA(sProjectRoot), NULL);\r
-               //if (sha1)\r
-               //      youngest = ConvertHashToRevnum(sha1);\r
+               // done to match TSVN functionality of this function (not sure if any code uses the reutrn val)\r
+               // if TGit does not need this, then change the return type of function\r
+               youngest = g_Git.GetHash(CString(_T("HEAD")));\r
        }\r
 \r
        return youngest;\r
index 08dc76a..f626f97 100644 (file)
@@ -75,7 +75,7 @@
                                AdditionalDependencies="Crypt32.lib"\r
                                OutputFile="$(OutDir)/TGitCache.exe"\r
                                LinkIncremental="2"\r
-                               AdditionalLibraryDirectories="../../ext/wingit"\r
+                               AdditionalLibraryDirectories=""\r
                                IgnoreDefaultLibraryNames="libc"\r
                                GenerateDebugInformation="true"\r
                                ProgramDatabaseFile="$(OutDir)/TGitCache.pdb"\r
                        />\r
                        <Tool\r
                                Name="VCLinkerTool"\r
-                               AdditionalDependencies="Crypt32.lib wingit.lib"\r
+                               AdditionalDependencies="Crypt32.lib"\r
                                OutputFile="$(OutDir)/TGitCache.exe"\r
                                LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="../../ext/wingit"\r
-                               DelayLoadDLLs="wingit.dll"\r
+                               AdditionalLibraryDirectories=""\r
+                               DelayLoadDLLs=""\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
                                OptimizeReferences="2"\r
index ba34f3c..390bcc1 100644 (file)
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="Crypt32.lib gdiplus.lib shfolder.lib shell32.lib comctl32.lib ws2_32.lib rpcrt4.lib shlwapi.lib wininet.lib version.lib"\r
                                LinkIncremental="1"\r
-                               AdditionalLibraryDirectories="../../ext/wingit"\r
                                AdditionalLibraryDirectories=""\r
                                GenerateDebugInformation="true"\r
                                SubSystem="2"\r
index 287e40e..e0b7463 100644 (file)
@@ -359,6 +359,7 @@ void CShellExt::GetColumnStatus(const TCHAR * path, BOOL bIsDir)
                }\r
                break;\r
        case ShellCache::dll:\r
+       case ShellCache::dllFull:\r
                {\r
                        status = m_CachedStatus.GetFullStatus(CTSVNPath(path), bIsDir, TRUE);\r
                        filestatus = status->status;\r
index c341248..a37baf4 100644 (file)
@@ -157,6 +157,8 @@ CShellExt::MenuInfo CShellExt::menuInfo[] =
 \r
        { ShellMenuBlame,                                               MENUBLAME,                      IDI_BLAME,                              IDS_MENUBLAME,                          IDS_MENUDESCBLAME,\r
        ITEMIS_NORMAL|ITEMIS_ONLYONE, ITEMIS_FOLDER|ITEMIS_ADDED, 0, 0, 0, 0, 0, 0 },\r
+       // TODO: original code is ITEMIS_INSVN|ITEMIS_ONLYONE, makes sense to only allow blaming of versioned files\r
+       //       why was this changed, is this related to GitStatus?\r
 \r
        { ShellMenuIgnoreSub,                                   MENUIGNORE,                     IDI_IGNORE,                             IDS_MENUIGNORE,                         IDS_MENUDESCIGNORE,\r
        ITEMIS_INVERSIONEDFOLDER, ITEMIS_IGNORED|ITEMIS_INSVN, 0, 0, 0, 0, 0, 0 },\r
@@ -336,13 +338,14 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                ATLTRACE2(_T("Exception in GitStatus::GetStatus()\n"));\r
                                                        }\r
 \r
+                                                       // TODO: should we really assume any sub-directory to be versioned\r
+                                                       //       or only if it contains versioned files\r
                                                        if ( askedpath.IsDirectory() )\r
                                                        {\r
                                                                if (askedpath.HasAdminDir())\r
                                                                        itemStates |= ITEMIS_INSVN;\r
                                                        }\r
                                                        if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                       //if (askedpath.HasAdminDir())\r
                                                                itemStates |= ITEMIS_INSVN;\r
                                                        if (status == git_wc_status_ignored)\r
                                                                itemStates |= ITEMIS_IGNORED;\r
@@ -444,13 +447,14 @@ STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder,
                                                                }\r
                                                        }\r
 \r
+                                                       // TODO: should we really assume any sub-directory to be versioned\r
+                                                       //       or only if it contains versioned files\r
                                                        if ( strpath.IsDirectory() )\r
                                                        {\r
                                                                if (strpath.HasAdminDir())\r
                                                                        itemStates |= ITEMIS_INSVN;\r
                                                        }\r
                                                        if ((status != git_wc_status_unversioned)&&(status != git_wc_status_ignored)&&(status != git_wc_status_none))\r
-                                                       //if (strpath.HasAdminDir())\r
                                                                itemStates |= ITEMIS_INSVN;\r
                                                        if (status == git_wc_status_ignored)\r
                                                        {\r
index 2b76670..28a59a0 100644 (file)
@@ -152,6 +152,7 @@ STDMETHODIMP CShellExt::IsMemberOf(LPCWSTR pwszPath, DWORD /*dwAttrib*/)
                        }\r
                        break;\r
                case ShellCache::dll:\r
+               case ShellCache::dllFull:\r
                        {\r
                                // Look in our caches for this item \r
                                const FileStatusCacheEntry * s = m_CachedStatus.GetCachedItem(CTGitPath(pPath));\r
@@ -243,6 +244,8 @@ 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
index f40783d..a08436f 100644 (file)
@@ -43,7 +43,8 @@ public:
        {\r
                none,\r
                exe,\r
-               dll\r
+               dll,\r
+               dllFull,// same as dll except it uses commandline git tool with all status modes supported\r
        };\r
        ShellCache()\r
        {\r