--- /dev/null
+// TortoiseGit - a Windows shell extension for easy version control\r
+\r
+// Copyright (C) 2003-2008 - TortoiseGit\r
+\r
+// This program is free software; you can redistribute it and/or\r
+// modify it under the terms of the GNU General Public License\r
+// as published by the Free Software Foundation; either version 2\r
+// of the License, or (at your option) any later version.\r
+\r
+// This program is distributed in the hope that it will be useful,\r
+// but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+// GNU General Public License for more details.\r
+\r
+// You should have received a copy of the GNU General Public License\r
+// along with this program; if not, write to the Free Software Foundation,\r
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+//\r
+\r
+#include "stdafx.h"\r
+//#include "resource.h"\r
+#include "..\TortoiseShell\resource.h"\r
+//#include "git_config.h"\r
+#include "GitStatus.h"\r
+#include "UnicodeUtils.h"\r
+//#include "GitGlobal.h"\r
+//#include "GitHelpers.h"\r
+#ifdef _MFC_VER\r
+//# include "Git.h"\r
+//# include "MessageBox.h"\r
+//# include "registry.h"\r
+//# include "TGitPath.h"\r
+//# include "PathUtils.h"\r
+#endif\r
+\r
+GitStatus::GitStatus(bool * pbCanceled)\r
+ : status(NULL)\r
+{\r
+#if 0\r
+ m_pool = git_pool_create (NULL);\r
+ \r
+ git_error_clear(git_client_create_context(&ctx, m_pool));\r
+ \r
+ if (pbCanceled)\r
+ {\r
+ ctx->cancel_func = cancel;\r
+ ctx->cancel_baton = pbCanceled;\r
+ }\r
+\r
+#ifdef _MFC_VER\r
+ git_error_clear(git_config_ensure(NULL, m_pool));\r
+ \r
+ // set up authentication\r
+ m_prompt.Init(m_pool, ctx);\r
+\r
+ // set up the configuration\r
+ m_err = git_config_get_config (&(ctx->config), g_pConfigDir, m_pool);\r
+\r
+ if (m_err)\r
+ {\r
+ ::MessageBox(NULL, this->GetLastErrorMsg(), _T("TortoiseGit"), MB_ICONERROR);\r
+ git_error_clear(m_err);\r
+ git_pool_destroy (m_pool); // free the allocated memory\r
+ exit(-1);\r
+ }\r
+\r
+ // set up the Git_SSH param\r
+ CString tgit_ssh = CRegString(_T("Software\\TortoiseGit\\SSH"));\r
+ if (tgit_ssh.IsEmpty())\r
+ tgit_ssh = CPathUtils::GetAppDirectory() + _T("TortoisePlink.exe");\r
+ tgit_ssh.Replace('\\', '/');\r
+ if (!tgit_ssh.IsEmpty())\r
+ {\r
+ git_config_t * cfg = (git_config_t *)apr_hash_get ((apr_hash_t *)ctx->config, Git_CONFIG_CATEGORY_CONFIG,\r
+ APR_HASH_KEY_STRING);\r
+ git_config_set(cfg, Git_CONFIG_SECTION_TUNNELS, "ssh", CUnicodeUtils::GetUTF8(tgit_ssh));\r
+ }\r
+#else\r
+ git_error_clear(git_config_ensure(NULL, m_pool));\r
+\r
+ // set up the configuration\r
+ m_err = git_config_get_config (&(ctx->config), g_pConfigDir, m_pool);\r
+\r
+#endif\r
+#endif\r
+}\r
+\r
+GitStatus::~GitStatus(void)\r
+{\r
+#if 0\r
+ git_error_clear(m_err);\r
+ git_pool_destroy (m_pool); // free the allocated memory\r
+#endif\r
+}\r
+\r
+void GitStatus::ClearPool()\r
+{\r
+#if 0\r
+ git_pool_clear(m_pool);\r
+#endif\r
+}\r
+\r
+#ifdef _MFC_VER\r
+CString GitStatus::GetLastErrorMsg() const\r
+{\r
+// return Git::GetErrorString(m_err);\r
+ return CString("");\r
+}\r
+#else\r
+stdstring GitStatus::GetLastErrorMsg() const\r
+{\r
+\r
+ stdstring msg;\r
+#if 0\r
+ char errbuf[256];\r
+\r
+ if (m_err != NULL)\r
+ {\r
+ git_error_t * ErrPtr = m_err;\r
+ if (ErrPtr->message)\r
+ {\r
+ msg = CUnicodeUtils::StdGetUnicode(ErrPtr->message);\r
+ }\r
+ else\r
+ {\r
+ /* Is this a Subversion-specific error code? */\r
+ if ((ErrPtr->apr_err > APR_OS_START_USEERR)\r
+ && (ErrPtr->apr_err <= APR_OS_START_CANONERR))\r
+ msg = CUnicodeUtils::StdGetUnicode(git_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)));\r
+ /* Otherwise, this must be an APR error code. */\r
+ else\r
+ {\r
+ git_error_t *temp_err = NULL;\r
+ const char * err_string = NULL;\r
+ temp_err = git_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);\r
+ if (temp_err)\r
+ {\r
+ git_error_clear (temp_err);\r
+ msg = _T("Can't recode error string from APR");\r
+ }\r
+ else\r
+ {\r
+ msg = CUnicodeUtils::StdGetUnicode(err_string);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ while (ErrPtr->child)\r
+ {\r
+ ErrPtr = ErrPtr->child;\r
+ msg += _T("\n");\r
+ if (ErrPtr->message)\r
+ {\r
+ msg += CUnicodeUtils::StdGetUnicode(ErrPtr->message);\r
+ }\r
+ else\r
+ {\r
+ /* Is this a Subversion-specific error code? */\r
+ if ((ErrPtr->apr_err > APR_OS_START_USEERR)\r
+ && (ErrPtr->apr_err <= APR_OS_START_CANONERR))\r
+ msg += CUnicodeUtils::StdGetUnicode(git_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)));\r
+ /* Otherwise, this must be an APR error code. */\r
+ else\r
+ {\r
+ git_error_t *temp_err = NULL;\r
+ const char * err_string = NULL;\r
+ temp_err = git_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);\r
+ if (temp_err)\r
+ {\r
+ git_error_clear (temp_err);\r
+ msg += _T("Can't recode error string from APR");\r
+ }\r
+ else\r
+ {\r
+ msg += CUnicodeUtils::StdGetUnicode(err_string);\r
+ }\r
+ }\r
+\r
+ }\r
+ }\r
+ return msg;\r
+ } // if (m_err != NULL)\r
+#endif\r
+ return msg;\r
+}\r
+#endif\r
+\r
+// static method\r
+git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth)\r
+{\r
+ git_wc_status_kind statuskind;\r
+#if 0\r
+ git_client_ctx_t * ctx;\r
+ \r
+ apr_pool_t * pool;\r
+ git_error_t * err;\r
+ BOOL isDir;\r
+\r
+ isDir = path.IsDirectory();\r
+ if (!path.HasAdminDir())\r
+ return git_wc_status_none;\r
+\r
+ pool = git_pool_create (NULL); // create the memory pool\r
+\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
+ statuskind = git_wc_status_none;\r
+ err = git_client_status4 (&youngest,\r
+ path.GetGitApiPath(pool),\r
+ &rev,\r
+ getallstatus,\r
+ &statuskind,\r
+ depth,\r
+ TRUE, //getall\r
+ FALSE, //update\r
+ TRUE, //noignore\r
+ FALSE, //ignore externals\r
+ NULL,\r
+ ctx,\r
+ pool);\r
+\r
+ // Error present\r
+ if (err != NULL)\r
+ {\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
+ return statuskind;\r
+}\r
+\r
+// static method\r
+git_wc_status_kind GitStatus::GetAllStatusRecursive(const CTGitPath& path)\r
+{\r
+ return GetAllStatus(path, git_depth_infinity);\r
+}\r
+\r
+// static method\r
+git_wc_status_kind GitStatus::GetMoreImportant(git_wc_status_kind status1, git_wc_status_kind status2)\r
+{\r
+ if (GetStatusRanking(status1) >= GetStatusRanking(status2))\r
+ return status1;\r
+ return status2;\r
+}\r
+// static private method\r
+int GitStatus::GetStatusRanking(git_wc_status_kind status)\r
+{\r
+ switch (status)\r
+ {\r
+ case git_wc_status_none:\r
+ return 0;\r
+ case git_wc_status_unversioned:\r
+ return 1;\r
+ case git_wc_status_ignored:\r
+ return 2;\r
+ case git_wc_status_incomplete:\r
+ return 4;\r
+ case git_wc_status_normal:\r
+ case git_wc_status_external:\r
+ return 5;\r
+ case git_wc_status_added:\r
+ return 6;\r
+ case git_wc_status_missing:\r
+ return 7;\r
+ case git_wc_status_deleted:\r
+ return 8;\r
+ case git_wc_status_replaced:\r
+ return 9;\r
+ case git_wc_status_modified:\r
+ return 10;\r
+ case git_wc_status_merged:\r
+ return 11;\r
+ case git_wc_status_conflicted:\r
+ return 12;\r
+ case git_wc_status_obstructed:\r
+ return 13;\r
+ }\r
+ return 0;\r
+}\r
+\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
+ \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
+ struct hashbaton_t hashbaton;\r
+ hashbaton.hash = statushash;\r
+ hashbaton.exthash = exthash;\r
+ hashbaton.pThis = this;\r
+ m_err = git_client_status4 (&youngest,\r
+ path.GetGitApiPath(m_pool),\r
+ &rev,\r
+ getstatushash,\r
+ &hashbaton,\r
+ git_depth_empty, //depth\r
+ TRUE, //getall\r
+ update, //update\r
+ noignore, //noignore\r
+ noexternals,\r
+ NULL,\r
+ ctx,\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
+ {\r
+ status = NULL;\r
+ return -2; \r
+ }\r
+\r
+ // Convert the unordered hash to an ordered, sorted array\r
+ statusarray = sort_hash (statushash,\r
+ sort_compare_items_as_paths,\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
+ \r
+ return youngest;\r
+#endif\r
+ return CString("");\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
+#if 0\r
+ const sort_item* item;\r
+\r
+ git_error_clear(m_err);\r
+ m_statushash = apr_hash_make(m_pool);\r
+ m_externalhash = apr_hash_make(m_pool);\r
+ headrev = Git_INVALID_REVNUM;\r
+ git_opt_revision_t rev;\r
+ rev.kind = git_opt_revision_unspecified;\r
+ struct hashbaton_t hashbaton;\r
+ hashbaton.hash = m_statushash;\r
+ hashbaton.exthash = m_externalhash;\r
+ hashbaton.pThis = this;\r
+ m_statushashindex = 0;\r
+ m_err = git_client_status4 (&headrev,\r
+ path.GetGitApiPath(m_pool),\r
+ &rev,\r
+ getstatushash,\r
+ &hashbaton,\r
+ depth,\r
+ TRUE, //getall\r
+ update, //update\r
+ bNoIgnore, //noignore\r
+ bNoExternals, //noexternals\r
+ NULL,\r
+ ctx,\r
+ m_pool);\r
+\r
+\r
+ // Error present if function is not under version control\r
+ if ((m_err != NULL) || (apr_hash_count(m_statushash) == 0))\r
+ {\r
+ return NULL; \r
+ }\r
+\r
+ // Convert the unordered hash to an ordered, sorted array\r
+ m_statusarray = sort_hash (m_statushash,\r
+ sort_compare_items_as_paths,\r
+ m_pool);\r
+\r
+ // only the first entry is needed (no recurse)\r
+ m_statushashindex = 0;\r
+ item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
+ retPath.SetFromGit((const char*)item->key);\r
+ return (git_wc_status2_t *) item->value;\r
+#endif\r
+\r
+ return 0;\r
+}\r
+\r
+unsigned int GitStatus::GetVersionedCount() const\r
+{\r
+\r
+ unsigned int count = 0;\r
+#if 0\r
+ const sort_item* item;\r
+ for (unsigned int i=0; i<apr_hash_count(m_statushash); ++i)\r
+ {\r
+ item = &APR_ARRAY_IDX(m_statusarray, i, const sort_item);\r
+ if (item)\r
+ {\r
+ if (GitStatus::GetMoreImportant(((git_wc_status_t *)item->value)->text_status, git_wc_status_ignored)!=git_wc_status_ignored)\r
+ count++; \r
+ }\r
+ }\r
+#endif\r
+ return count;\r
+}\r
+\r
+git_wc_status2_t * GitStatus::GetNextFileStatus(CTGitPath& retPath)\r
+{\r
+#if 0\r
+ const sort_item* item;\r
+\r
+ if ((m_statushashindex+1) >= apr_hash_count(m_statushash))\r
+ return NULL;\r
+ m_statushashindex++;\r
+\r
+ item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
+ retPath.SetFromGit((const char*)item->key);\r
+ return (git_wc_status2_t *) item->value;\r
+#endif\r
+ return 0;\r
+}\r
+\r
+bool GitStatus::IsExternal(const CTGitPath& path) const\r
+{\r
+#if 0\r
+ if (apr_hash_get(m_externalhash, path.GetGitApiPath(m_pool), APR_HASH_KEY_STRING))\r
+ return true;\r
+#endif\r
+ return false;\r
+}\r
+\r
+bool GitStatus::IsInExternal(const CTGitPath& path) const\r
+{\r
+#if 0\r
+ if (apr_hash_count(m_statushash) == 0)\r
+ return false;\r
+\r
+ GitPool localpool(m_pool);\r
+ apr_hash_index_t *hi;\r
+ const char* key;\r
+ for (hi = apr_hash_first(localpool, m_externalhash); hi; hi = apr_hash_next(hi)) \r
+ {\r
+ apr_hash_this(hi, (const void**)&key, NULL, NULL);\r
+ if (key)\r
+ {\r
+ if (CTGitPath(CUnicodeUtils::GetUnicode(key)).IsAncestorOf(path))\r
+ return true;\r
+ }\r
+ }\r
+#endif\r
+ return false;\r
+}\r
+\r
+\r
+void GitStatus::GetStatusString(git_wc_status_kind status, size_t buflen, TCHAR * string)\r
+{\r
+ TCHAR * buf;\r
+ switch (status)\r
+ {\r
+ case git_wc_status_none:\r
+ buf = _T("none\0");\r
+ break;\r
+ case git_wc_status_unversioned:\r
+ buf = _T("unversioned\0");\r
+ break;\r
+ case git_wc_status_normal:\r
+ buf = _T("normal\0");\r
+ break;\r
+ case git_wc_status_added:\r
+ buf = _T("added\0");\r
+ break;\r
+ case git_wc_status_missing:\r
+ buf = _T("missing\0");\r
+ break;\r
+ case git_wc_status_deleted:\r
+ buf = _T("deleted\0");\r
+ break;\r
+ case git_wc_status_replaced:\r
+ buf = _T("replaced\0");\r
+ break;\r
+ case git_wc_status_modified:\r
+ buf = _T("modified\0");\r
+ break;\r
+ case git_wc_status_merged:\r
+ buf = _T("merged\0");\r
+ break;\r
+ case git_wc_status_conflicted:\r
+ buf = _T("conflicted\0");\r
+ break;\r
+ case git_wc_status_obstructed:\r
+ buf = _T("obstructed\0");\r
+ break;\r
+ case git_wc_status_ignored:\r
+ buf = _T("ignored");\r
+ break;\r
+ case git_wc_status_external:\r
+ buf = _T("external");\r
+ break;\r
+ case git_wc_status_incomplete:\r
+ buf = _T("incomplete\0");\r
+ break;\r
+ default:\r
+ buf = _T("\0");\r
+ break;\r
+ }\r
+ _stprintf_s(string, buflen, _T("%s"), buf);\r
+}\r
+\r
+void GitStatus::GetStatusString(HINSTANCE hInst, git_wc_status_kind status, TCHAR * string, int size, WORD lang)\r
+{\r
+ switch (status)\r
+ {\r
+ case git_wc_status_none:\r
+ LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
+ break;\r
+ case git_wc_status_unversioned:\r
+ LoadStringEx(hInst, IDS_STATUSUNVERSIONED, string, size, lang);\r
+ break;\r
+ case git_wc_status_normal:\r
+ LoadStringEx(hInst, IDS_STATUSNORMAL, string, size, lang);\r
+ break;\r
+ case git_wc_status_added:\r
+ LoadStringEx(hInst, IDS_STATUSADDED, string, size, lang);\r
+ break;\r
+ case git_wc_status_missing:\r
+ LoadStringEx(hInst, IDS_STATUSABSENT, string, size, lang);\r
+ break;\r
+ case git_wc_status_deleted:\r
+ LoadStringEx(hInst, IDS_STATUSDELETED, string, size, lang);\r
+ break;\r
+ case git_wc_status_replaced:\r
+ LoadStringEx(hInst, IDS_STATUSREPLACED, string, size, lang);\r
+ break;\r
+ case git_wc_status_modified:\r
+ LoadStringEx(hInst, IDS_STATUSMODIFIED, string, size, lang);\r
+ break;\r
+ case git_wc_status_merged:\r
+ LoadStringEx(hInst, IDS_STATUSMERGED, string, size, lang);\r
+ break;\r
+ case git_wc_status_conflicted:\r
+ LoadStringEx(hInst, IDS_STATUSCONFLICTED, string, size, lang);\r
+ break;\r
+ case git_wc_status_ignored:\r
+ LoadStringEx(hInst, IDS_STATUSIGNORED, string, size, lang);\r
+ break;\r
+ case git_wc_status_obstructed:\r
+ LoadStringEx(hInst, IDS_STATUSOBSTRUCTED, string, size, lang);\r
+ break;\r
+ case git_wc_status_external:\r
+ LoadStringEx(hInst, IDS_STATUSEXTERNAL, string, size, lang);\r
+ break;\r
+ case git_wc_status_incomplete:\r
+ LoadStringEx(hInst, IDS_STATUSINCOMPLETE, string, size, lang);\r
+ break;\r
+ default:\r
+ LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
+ break;\r
+ }\r
+}\r
+\r
+#ifdef _MFC_VER\r
+CString GitStatus::GetDepthString(git_depth_t depth)\r
+{\r
+#if 0\r
+ CString sDepth;\r
+ switch (depth)\r
+ {\r
+ case git_depth_unknown:\r
+ sDepth.LoadString(IDS_Git_DEPTH_UNKNOWN);\r
+ break;\r
+ case git_depth_empty:\r
+ sDepth.LoadString(IDS_Git_DEPTH_EMPTY);\r
+ break;\r
+ case git_depth_files:\r
+ sDepth.LoadString(IDS_Git_DEPTH_FILES);\r
+ break;\r
+ case git_depth_immediates:\r
+ sDepth.LoadString(IDS_Git_DEPTH_IMMEDIATE);\r
+ break;\r
+ case git_depth_infinity:\r
+ sDepth.LoadString(IDS_Git_DEPTH_INFINITE);\r
+ break;\r
+ }\r
+ return sDepth;\r
+#endif\r
+ return CString("");\r
+}\r
+#endif\r
+\r
+void GitStatus::GetDepthString(HINSTANCE hInst, git_depth_t depth, TCHAR * string, int size, WORD lang)\r
+{\r
+#if 0\r
+ switch (depth)\r
+ {\r
+ case git_depth_unknown:\r
+ LoadStringEx(hInst, IDS_SVN_DEPTH_UNKNOWN, string, size, lang);\r
+ break;\r
+ case git_depth_empty:\r
+ LoadStringEx(hInst, IDS_SVN_DEPTH_EMPTY, string, size, lang);\r
+ break;\r
+ case git_depth_files:\r
+ LoadStringEx(hInst, IDS_SVN_DEPTH_FILES, string, size, lang);\r
+ break;\r
+ case git_depth_immediates:\r
+ LoadStringEx(hInst, IDS_SVN_DEPTH_IMMEDIATE, string, size, lang);\r
+ break;\r
+ case git_depth_infinity:\r
+ LoadStringEx(hInst, IDS_SVN_DEPTH_INFINITE, string, size, lang);\r
+ break;\r
+ }\r
+#endif\r
+}\r
+\r
+\r
+int GitStatus::LoadStringEx(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax, WORD wLanguage)\r
+{\r
+ const STRINGRESOURCEIMAGE* pImage;\r
+ const STRINGRESOURCEIMAGE* pImageEnd;\r
+ ULONG nResourceSize;\r
+ HGLOBAL hGlobal;\r
+ UINT iIndex;\r
+ int ret;\r
+\r
+ HRSRC hResource = FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE(((uID>>4)+1)), wLanguage);\r
+ if (!hResource)\r
+ {\r
+ // try the default language before giving up!\r
+ hResource = FindResource(hInstance, MAKEINTRESOURCE(((uID>>4)+1)), RT_STRING);\r
+ if (!hResource)\r
+ return 0;\r
+ }\r
+ hGlobal = LoadResource(hInstance, hResource);\r
+ if (!hGlobal)\r
+ return 0;\r
+ pImage = (const STRINGRESOURCEIMAGE*)::LockResource(hGlobal);\r
+ if(!pImage)\r
+ return 0;\r
+\r
+ nResourceSize = ::SizeofResource(hInstance, hResource);\r
+ pImageEnd = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+nResourceSize);\r
+ iIndex = uID&0x000f;\r
+\r
+ while ((iIndex > 0) && (pImage < pImageEnd))\r
+ {\r
+ pImage = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+(sizeof(STRINGRESOURCEIMAGE)+(pImage->nLength*sizeof(WCHAR))));\r
+ iIndex--;\r
+ }\r
+ if (pImage >= pImageEnd)\r
+ return 0;\r
+ if (pImage->nLength == 0)\r
+ return 0;\r
+\r
+ ret = pImage->nLength;\r
+ if (pImage->nLength > nBufferMax)\r
+ {\r
+ wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength-1);\r
+ lpBuffer[nBufferMax-1] = 0;\r
+ }\r
+ else\r
+ {\r
+ wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength);\r
+ lpBuffer[ret] = 0;\r
+ }\r
+ return ret;\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
+ git_wc_status_kind * s = (git_wc_status_kind *)baton;\r
+ *s = GitStatus::GetMoreImportant(*s, status->text_status);\r
+ *s = GitStatus::GetMoreImportant(*s, status->prop_status);\r
+ return Git_NO_ERROR;\r
+}\r
+#endif\r
+\r
+#if 0\r
+git_error_t * GitStatus::getstatushash(void * baton, const char * path, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
+{\r
+ hashbaton_t * hash = (hashbaton_t *)baton;\r
+ const StdStrAVector& filterList = hash->pThis->m_filterFileList;\r
+ if (status->text_status == git_wc_status_external)\r
+ {\r
+ apr_hash_set (hash->exthash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, (const void*)1);\r
+ return Git_NO_ERROR;\r
+ }\r
+ if(filterList.size() > 0)\r
+ {\r
+ // We have a filter active - we're only interested in files which are in \r
+ // the filter \r
+ if(!binary_search(filterList.begin(), filterList.end(), path))\r
+ {\r
+ // This item is not in the filter - don't store it\r
+ return Git_NO_ERROR;\r
+ }\r
+ }\r
+ git_wc_status2_t * statuscopy = git_wc_dup_status2 (status, hash->pThis->m_pool);\r
+ apr_hash_set (hash->hash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, statuscopy);\r
+ return Git_NO_ERROR;\r
+}\r
+\r
+apr_array_header_t * GitStatus::sort_hash (apr_hash_t *ht,\r
+ int (*comparison_func) (const GitStatus::sort_item *, const GitStatus::sort_item *),\r
+ apr_pool_t *pool)\r
+{\r
+ apr_hash_index_t *hi;\r
+ apr_array_header_t *ary;\r
+\r
+ /* allocate an array with only one element to begin with. */\r
+ ary = apr_array_make (pool, 1, sizeof(sort_item));\r
+\r
+ /* loop over hash table and push all keys into the array */\r
+ for (hi = apr_hash_first (pool, ht); hi; hi = apr_hash_next (hi))\r
+ {\r
+ sort_item *item = (sort_item*)apr_array_push (ary);\r
+\r
+ apr_hash_this (hi, &item->key, &item->klen, &item->value);\r
+ }\r
+\r
+ /* now quick sort the array. */\r
+ qsort (ary->elts, ary->nelts, ary->elt_size,\r
+ (int (*)(const void *, const void *))comparison_func);\r
+\r
+ return ary;\r
+}\r
+\r
+int GitStatus::sort_compare_items_as_paths (const sort_item *a, const sort_item *b)\r
+{\r
+ const char *astr, *bstr;\r
+\r
+ astr = (const char*)a->key;\r
+ bstr = (const char*)b->key;\r
+ return git_path_compare_paths (astr, bstr);\r
+}\r
+#endif\r
+\r
+git_error_t* GitStatus::cancel(void *baton)\r
+{\r
+#if 0\r
+ volatile bool * canceled = (bool *)baton;\r
+ if (*canceled)\r
+ {\r
+ CString temp;\r
+ temp.LoadString(IDS_Git_USERCANCELLED);\r
+ return git_error_create(Git_ERR_CANCELLED, NULL, CUnicodeUtils::GetUTF8(temp));\r
+ }\r
+ return Git_NO_ERROR;\r
+#endif \r
+ return 0;\r
+}\r
+\r
+#ifdef _MFC_VER\r
+\r
+// Set-up a filter to restrict the files which will have their status stored by a get-status\r
+void GitStatus::SetFilter(const CTGitPathList& fileList)\r
+{\r
+ m_filterFileList.clear();\r
+ for(int fileIndex = 0; fileIndex < fileList.GetCount(); fileIndex++)\r
+ {\r
+// m_filterFileList.push_back(fileList[fileIndex].GetGitApiPath(m_pool));\r
+ }\r
+ // Sort the list so that we can do binary searches\r
+ std::sort(m_filterFileList.begin(), m_filterFileList.end());\r
+}\r
+\r
+void GitStatus::ClearFilter()\r
+{\r
+ m_filterFileList.clear();\r
+}\r
+\r
+#endif // _MFC_VER\r
+\r