OSDN Git Service

Change Progress.h to SysProgress.h because there are two progress.h file.
[tortoisegit/TortoiseGitJp.git] / src / Git / GitStatus.cpp
index 8e7ae07..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
 //#    include "TGitPath.h"\r
 //#    include "PathUtils.h"\r
 #endif\r
+#include "git.h"\r
+#include "gitindex.h"\r
+\r
+CGitIndexFileMap g_IndexFileMap;\r
 \r
 GitStatus::GitStatus(bool * pbCanceled)\r
        : status(NULL)\r
@@ -189,27 +198,77 @@ stdstring GitStatus::GetLastErrorMsg() const
 // static method\r
 git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth)\r
 {\r
-       git_wc_status_kind                      statuskind = git_wc_status_none;\r
-#if 0\r
-       git_client_ctx_t *                      ctx;\r
+       git_wc_status_kind                      statuskind;\r
+//     git_client_ctx_t *                      ctx;\r
        \r
-       apr_pool_t *                            pool;\r
-       git_error_t *                           err;\r
+//     apr_pool_t *                            pool;\r
+//     git_error_t *                           err;\r
+       BOOL                                            err;\r
        BOOL                                            isDir;\r
+       CString                                         sProjectRoot;\r
 \r
        isDir = path.IsDirectory();\r
-       if (!path.HasAdminDir())\r
+       if (!path.HasAdminDir(&sProjectRoot))\r
                return git_wc_status_none;\r
 \r
-       pool = git_pool_create (NULL);                          // create the memory pool\r
+//     pool = git_pool_create (NULL);                          // create the memory pool\r
 \r
-       git_error_clear(git_client_create_context(&ctx, pool));\r
+//     git_error_clear(git_client_create_context(&ctx, pool));\r
 \r
-       git_revnum_t youngest = Git_INVALID_REVNUM;\r
-       git_opt_revision_t rev;\r
-       rev.kind = git_opt_revision_unspecified;\r
-       err = git_client_status4 (&youngest,\r
-                                                       path.GetGitApiPath(pool),\r
+//     git_revnum_t youngest = Git_INVALID_REVNUM;\r
+//     git_opt_revision_t rev;\r
+//     rev.kind = git_opt_revision_unspecified;\r
+       statuskind = git_wc_status_none;\r
+\r
+       const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source\r
+\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
+               // 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
+#else\r
+               // enumerate all files, recursively if requested\r
+               UINT nFlags = 0;\r
+               if (!bIsRecursive)\r
+                       nFlags |= WGEFF_NoRecurse;\r
+#endif\r
+\r
+               err = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
+\r
+               /*err = git_client_status4 (&youngest,\r
+                                                       path.GetSVNApiPath(pool),\r
                                                        &rev,\r
                                                        getallstatus,\r
                                                        &statuskind,\r
@@ -220,18 +279,19 @@ git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t de
                                                        FALSE,          //ignore externals\r
                                                        NULL,\r
                                                        ctx,\r
-                                                       pool);\r
+                                                       pool);*/\r
+       }\r
 \r
        // Error present\r
        if (err != NULL)\r
        {\r
-               git_error_clear(err);\r
-               git_pool_destroy (pool);                                //free allocated memory\r
+//             git_error_clear(err);\r
+//             git_pool_destroy (pool);                                //free allocated memory\r
                return git_wc_status_none;      \r
        }\r
 \r
-       git_pool_destroy (pool);                                //free allocated memory\r
-#endif\r
+//     git_pool_destroy (pool);                                //free allocated memory\r
+\r
        return statuskind;\r
 }\r
 \r
@@ -286,23 +346,73 @@ int GitStatus::GetStatusRanking(git_wc_status_kind status)
 \r
 git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false */, bool noignore /* = false */, bool noexternals /* = false */)\r
 {\r
-#if 0\r
-       apr_hash_t *                            statushash;\r
-       apr_hash_t *                            exthash;\r
-       apr_array_header_t *            statusarray;\r
-       const sort_item*                        item;\r
+       // NOTE: unlike the SVN version this one does not cache the enumerated files, because in practice no code in all of\r
+       //       Tortoise uses this, all places that call GetStatus create a temp GitStatus object which gets destroyed right\r
+       //       after the call again\r
+\r
+//     apr_hash_t *                            statushash;\r
+//     apr_hash_t *                            exthash;\r
+//     apr_array_header_t *            statusarray;\r
+//     const sort_item*                        item;\r
        \r
-       git_error_clear(m_err);\r
-       statushash = apr_hash_make(m_pool);\r
-       exthash = apr_hash_make(m_pool);\r
-       git_revnum_t youngest = Git_INVALID_REVNUM;\r
-       git_opt_revision_t rev;\r
-       rev.kind = git_opt_revision_unspecified;\r
+//     git_error_clear(m_err);\r
+//     statushash = apr_hash_make(m_pool);\r
+//     exthash = apr_hash_make(m_pool);\r
+       git_revnum_t youngest = GIT_INVALID_REVNUM;\r
+//     git_opt_revision_t rev;\r
+//     rev.kind = git_opt_revision_unspecified;\r
+\r
+       CString sProjectRoot;\r
+       if ( !path.HasAdminDir(&sProjectRoot) )\r
+               return youngest;\r
+\r
        struct hashbaton_t hashbaton;\r
-       hashbaton.hash = statushash;\r
-       hashbaton.exthash = exthash;\r
+//     hashbaton.hash = statushash;\r
+//     hashbaton.exthash = exthash;\r
        hashbaton.pThis = this;\r
-       m_err = git_client_status4 (&youngest,\r
+\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
+               // 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
+               // 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
+\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 = git_client_status4 (&youngest,\r
                                                        path.GetGitApiPath(m_pool),\r
                                                        &rev,\r
                                                        getstatushash,\r
@@ -314,32 +424,65 @@ git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false
                                                        noexternals,\r
                                                        NULL,\r
                                                        ctx,\r
-                                                       m_pool);\r
-\r
+                                                       m_pool);*/\r
+       }\r
 \r
        // Error present if function is not under version control\r
-       if ((m_err != NULL) || (apr_hash_count(statushash) == 0))\r
+       if (m_err) /*|| (apr_hash_count(statushash) == 0)*/\r
        {\r
                status = NULL;\r
-               return -2;      \r
+//             return -2;      \r
+               return GIT_INVALID_REVNUM;\r
        }\r
 \r
        // Convert the unordered hash to an ordered, sorted array\r
-       statusarray = sort_hash (statushash,\r
+       /*statusarray = sort_hash (statushash,\r
                                                          sort_compare_items_as_paths,\r
-                                                         m_pool);\r
+                                                         m_pool);*/\r
 \r
        // only the first entry is needed (no recurse)\r
-       item = &APR_ARRAY_IDX (statusarray, 0, const sort_item);\r
-       \r
-       status = (git_wc_status2_t *) item->value;\r
+//     item = &APR_ARRAY_IDX (statusarray, 0, const sort_item);\r
        \r
+//     status = (git_wc_status2_t *) item->value;\r
+       status = &m_status;\r
+\r
+       if (update)\r
+       {\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
-#endif\r
-       return CString("");\r
 }\r
+\r
 git_wc_status2_t * GitStatus::GetFirstFileStatus(const CTGitPath& path, CTGitPath& retPath, bool update, git_depth_t depth, bool bNoIgnore /* = true */, bool bNoExternals /* = false */)\r
 {\r
+       static git_wc_status2 st;\r
+/*\r
+       m_fileCache.Reset();\r
+\r
+       m_fileCache.Init( CStringA( path.GetWinPathString().GetString() ) );\r
+MessageBox(NULL, path.GetWinPathString(), _T("GetFirstFile"), MB_OK);\r
+       m_fileCache.m_pFileIter = m_fileCache.m_pFiles;\r
+       st.text_status = git_wc_status_none;\r
+\r
+       if (m_fileCache.m_pFileIter)\r
+       {\r
+               switch(m_fileCache.m_pFileIter->nStatus)\r
+               {\r
+               case WGFS_Normal: st.text_status = git_wc_status_normal; break;\r
+               case WGFS_Modified: st.text_status = git_wc_status_modified; break;\r
+               case WGFS_Deleted: st.text_status = git_wc_status_deleted; break;\r
+               }\r
+\r
+               //retPath.SetFromGit((const char*)item->key);\r
+\r
+               m_fileCache.m_pFileIter = m_fileCache.m_pFileIter->pNext;\r
+       }\r
+\r
+       return &st;\r
+*/\r
 #if 0\r
        const sort_item*                        item;\r
 \r
@@ -392,6 +535,7 @@ git_wc_status2_t * GitStatus::GetFirstFileStatus(const CTGitPath& path, CTGitPat
 \r
 unsigned int GitStatus::GetVersionedCount() const\r
 {\r
+//     return /**/m_fileCache.GetFileCount();\r
 \r
        unsigned int count = 0;\r
 #if 0\r
@@ -411,6 +555,24 @@ unsigned int GitStatus::GetVersionedCount() const
 \r
 git_wc_status2_t * GitStatus::GetNextFileStatus(CTGitPath& retPath)\r
 {\r
+       static git_wc_status2 st;\r
+\r
+       st.text_status = git_wc_status_none;\r
+\r
+       /*if (m_fileCache.m_pFileIter)\r
+       {\r
+               switch(m_fileCache.m_pFileIter->nStatus)\r
+               {\r
+               case WGFS_Normal: st.text_status = git_wc_status_normal; break;\r
+               case WGFS_Modified: st.text_status = git_wc_status_modified; break;\r
+               case WGFS_Deleted: st.text_status = git_wc_status_deleted; break;\r
+               }\r
+\r
+               m_fileCache.m_pFileIter = m_fileCache.m_pFileIter->pNext;\r
+       }*/\r
+\r
+       return &st;\r
+\r
 #if 0\r
        const sort_item*                        item;\r
 \r
@@ -669,6 +831,20 @@ int GitStatus::LoadStringEx(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int
        return ret;\r
 }\r
 \r
+BOOL GitStatus::getallstatus(const struct wgFile_s *pFile, void *pUserData)\r
+{\r
+       git_wc_status_kind * s = (git_wc_status_kind *)pUserData;\r
+       *s = GitStatus::GetMoreImportant(*s, GitStatusFromWingit(pFile->nStatus));\r
+       return FALSE;\r
+}\r
+\r
+BOOL GitStatus::getstatus(const struct wgFile_s *pFile, void *pUserData)\r
+{\r
+       git_wc_status2_t * s = (git_wc_status2_t*)pUserData;\r
+       s->prop_status = s->text_status = GitStatus::GetMoreImportant(s->prop_status, GitStatusFromWingit(pFile->nStatus));\r
+       return FALSE;\r
+}\r
+\r
 #if 0\r
 git_error_t * GitStatus::getallstatus(void * baton, const char * /*path*/, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
 {\r