OSDN Git Service

initial icon overlay support using the wingit lib
[tortoisegit/TortoiseGitJp.git] / src / Git / GitStatus.cpp
1 // TortoiseGit - a Windows shell extension for easy version control\r
2 \r
3 // Copyright (C) 2003-2008 - TortoiseGit\r
4 \r
5 // This program is free software; you can redistribute it and/or\r
6 // modify it under the terms of the GNU General Public License\r
7 // as published by the Free Software Foundation; either version 2\r
8 // of the License, or (at your option) any later version.\r
9 \r
10 // This program is distributed in the hope that it will be useful,\r
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 // GNU General Public License for more details.\r
14 \r
15 // You should have received a copy of the GNU General Public License\r
16 // along with this program; if not, write to the Free Software Foundation,\r
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
18 //\r
19 \r
20 #include "stdafx.h"\r
21 //#include "resource.h"\r
22 #include "..\TortoiseShell\resource.h"\r
23 //#include "git_config.h"\r
24 #include "GitStatus.h"\r
25 #include "UnicodeUtils.h"\r
26 //#include "GitGlobal.h"\r
27 //#include "GitHelpers.h"\r
28 #ifdef _MFC_VER\r
29 //#     include "Git.h"\r
30 //#     include "MessageBox.h"\r
31 //#     include "registry.h"\r
32 //#     include "TGitPath.h"\r
33 //#     include "PathUtils.h"\r
34 #endif\r
35 \r
36 \r
37 GitStatus::GitStatus(bool * pbCanceled)\r
38         : status(NULL)\r
39 {\r
40 #if 0\r
41         m_pool = git_pool_create (NULL);\r
42         \r
43         git_error_clear(git_client_create_context(&ctx, m_pool));\r
44         \r
45         if (pbCanceled)\r
46         {\r
47                 ctx->cancel_func = cancel;\r
48                 ctx->cancel_baton = pbCanceled;\r
49         }\r
50 \r
51 #ifdef _MFC_VER\r
52         git_error_clear(git_config_ensure(NULL, m_pool));\r
53         \r
54         // set up authentication\r
55         m_prompt.Init(m_pool, ctx);\r
56 \r
57         // set up the configuration\r
58         m_err = git_config_get_config (&(ctx->config), g_pConfigDir, m_pool);\r
59 \r
60         if (m_err)\r
61         {\r
62                 ::MessageBox(NULL, this->GetLastErrorMsg(), _T("TortoiseGit"), MB_ICONERROR);\r
63                 git_error_clear(m_err);\r
64                 git_pool_destroy (m_pool);                                      // free the allocated memory\r
65                 exit(-1);\r
66         }\r
67 \r
68         // set up the Git_SSH param\r
69         CString tgit_ssh = CRegString(_T("Software\\TortoiseGit\\SSH"));\r
70         if (tgit_ssh.IsEmpty())\r
71                 tgit_ssh = CPathUtils::GetAppDirectory() + _T("TortoisePlink.exe");\r
72         tgit_ssh.Replace('\\', '/');\r
73         if (!tgit_ssh.IsEmpty())\r
74         {\r
75                 git_config_t * cfg = (git_config_t *)apr_hash_get ((apr_hash_t *)ctx->config, Git_CONFIG_CATEGORY_CONFIG,\r
76                         APR_HASH_KEY_STRING);\r
77                 git_config_set(cfg, Git_CONFIG_SECTION_TUNNELS, "ssh", CUnicodeUtils::GetUTF8(tgit_ssh));\r
78         }\r
79 #else\r
80         git_error_clear(git_config_ensure(NULL, m_pool));\r
81 \r
82         // set up the configuration\r
83         m_err = git_config_get_config (&(ctx->config), g_pConfigDir, m_pool);\r
84 \r
85 #endif\r
86 #endif\r
87 }\r
88 \r
89 GitStatus::~GitStatus(void)\r
90 {\r
91 #if 0\r
92         git_error_clear(m_err);\r
93         git_pool_destroy (m_pool);                                      // free the allocated memory\r
94 #endif\r
95 }\r
96 \r
97 void GitStatus::ClearPool()\r
98 {\r
99 #if 0\r
100         git_pool_clear(m_pool);\r
101 #endif\r
102 }\r
103 \r
104 #ifdef _MFC_VER\r
105 CString GitStatus::GetLastErrorMsg() const\r
106 {\r
107 //      return Git::GetErrorString(m_err);\r
108         return CString("");\r
109 }\r
110 #else\r
111 stdstring GitStatus::GetLastErrorMsg() const\r
112 {\r
113 \r
114         stdstring msg;\r
115 #if 0\r
116         char errbuf[256];\r
117 \r
118         if (m_err != NULL)\r
119         {\r
120                 git_error_t * ErrPtr = m_err;\r
121                 if (ErrPtr->message)\r
122                 {\r
123                         msg = CUnicodeUtils::StdGetUnicode(ErrPtr->message);\r
124                 }\r
125                 else\r
126                 {\r
127                         /* Is this a Subversion-specific error code? */\r
128                         if ((ErrPtr->apr_err > APR_OS_START_USEERR)\r
129                                 && (ErrPtr->apr_err <= APR_OS_START_CANONERR))\r
130                                 msg = CUnicodeUtils::StdGetUnicode(git_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)));\r
131                         /* Otherwise, this must be an APR error code. */\r
132                         else\r
133                         {\r
134                                 git_error_t *temp_err = NULL;\r
135                                 const char * err_string = NULL;\r
136                                 temp_err = git_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);\r
137                                 if (temp_err)\r
138                                 {\r
139                                         git_error_clear (temp_err);\r
140                                         msg = _T("Can't recode error string from APR");\r
141                                 }\r
142                                 else\r
143                                 {\r
144                                         msg = CUnicodeUtils::StdGetUnicode(err_string);\r
145                                 }\r
146                         }\r
147 \r
148                 }\r
149 \r
150                 while (ErrPtr->child)\r
151                 {\r
152                         ErrPtr = ErrPtr->child;\r
153                         msg += _T("\n");\r
154                         if (ErrPtr->message)\r
155                         {\r
156                                 msg += CUnicodeUtils::StdGetUnicode(ErrPtr->message);\r
157                         }\r
158                         else\r
159                         {\r
160                                 /* Is this a Subversion-specific error code? */\r
161                                 if ((ErrPtr->apr_err > APR_OS_START_USEERR)\r
162                                         && (ErrPtr->apr_err <= APR_OS_START_CANONERR))\r
163                                         msg += CUnicodeUtils::StdGetUnicode(git_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)));\r
164                                 /* Otherwise, this must be an APR error code. */\r
165                                 else\r
166                                 {\r
167                                         git_error_t *temp_err = NULL;\r
168                                         const char * err_string = NULL;\r
169                                         temp_err = git_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);\r
170                                         if (temp_err)\r
171                                         {\r
172                                                 git_error_clear (temp_err);\r
173                                                 msg += _T("Can't recode error string from APR");\r
174                                         }\r
175                                         else\r
176                                         {\r
177                                                 msg += CUnicodeUtils::StdGetUnicode(err_string);\r
178                                         }\r
179                                 }\r
180 \r
181                         }\r
182                 }\r
183                 return msg;\r
184         } // if (m_err != NULL)\r
185 #endif\r
186         return msg;\r
187 }\r
188 #endif\r
189 \r
190 // static method\r
191 git_wc_status_kind GitStatus::GetAllStatus(const CTGitPath& path, git_depth_t depth)\r
192 {\r
193         git_wc_status_kind                      statuskind;\r
194 //      git_client_ctx_t *                      ctx;\r
195         \r
196 //      apr_pool_t *                            pool;\r
197 //      git_error_t *                           err;\r
198         BOOL                                            err;\r
199         BOOL                                            isDir;\r
200         CString                                         sProjectRoot;\r
201 \r
202         isDir = path.IsDirectory();\r
203         if (!path.HasAdminDir(&sProjectRoot))\r
204                 return git_wc_status_none;\r
205 \r
206 //      pool = git_pool_create (NULL);                          // create the memory pool\r
207 \r
208 //      git_error_clear(git_client_create_context(&ctx, pool));\r
209 \r
210 //      git_revnum_t youngest = Git_INVALID_REVNUM;\r
211 //      git_opt_revision_t rev;\r
212 //      rev.kind = git_opt_revision_unspecified;\r
213         statuskind = git_wc_status_none;\r
214 \r
215         // TODO: not sure what to do with recursivenes, it's very unclear exactly what svn does, wingit will however return\r
216         //       the correct (recursive) status for folders, so WGEFF_NoRecurse can be specified to avoid unecessary processing\r
217         //const BOOL bIsRecursive = (depth == git_depth_infinity || depth == git_depth_unknown); // taken from SVN source\r
218         UINT nFlags = WGEFF_DirStatusAll;\r
219         //if (!bIsRecursive)\r
220                 nFlags |= WGEFF_NoRecurse;\r
221 \r
222         LPCSTR lpszSubPath = NULL;\r
223         CStringA sSubPath;\r
224         CString s = path.GetDirectory().GetWinPathString();\r
225         if (s.GetLength() > sProjectRoot.GetLength())\r
226         {\r
227                 sSubPath = CStringA(s.Right(s.GetLength() - sProjectRoot.GetLength() - 1/*otherwise it gets initial slash*/));\r
228                 lpszSubPath = sSubPath;\r
229         }\r
230 \r
231         err = !wgEnumFiles(CStringA(sProjectRoot), lpszSubPath, nFlags, &getallstatus, &statuskind);\r
232 \r
233         /*err = git_client_status4 (&youngest,\r
234                                                         path.GetSVNApiPath(pool),\r
235                                                         &rev,\r
236                                                         getallstatus,\r
237                                                         &statuskind,\r
238                                                         depth,\r
239                                                         TRUE,           //getall\r
240                                                         FALSE,          //update\r
241                                                         TRUE,           //noignore\r
242                                                         FALSE,          //ignore externals\r
243                                                         NULL,\r
244                                                         ctx,\r
245                                                         pool);*/\r
246 \r
247         // Error present\r
248         if (err != NULL)\r
249         {\r
250 //              git_error_clear(err);\r
251 //              git_pool_destroy (pool);                                //free allocated memory\r
252                 return git_wc_status_none;      \r
253         }\r
254 \r
255 //      git_pool_destroy (pool);                                //free allocated memory\r
256 \r
257         return statuskind;\r
258 }\r
259 \r
260 // static method\r
261 git_wc_status_kind GitStatus::GetAllStatusRecursive(const CTGitPath& path)\r
262 {\r
263         return GetAllStatus(path, git_depth_infinity);\r
264 }\r
265 \r
266 // static method\r
267 git_wc_status_kind GitStatus::GetMoreImportant(git_wc_status_kind status1, git_wc_status_kind status2)\r
268 {\r
269         if (GetStatusRanking(status1) >= GetStatusRanking(status2))\r
270                 return status1;\r
271         return status2;\r
272 }\r
273 // static private method\r
274 int GitStatus::GetStatusRanking(git_wc_status_kind status)\r
275 {\r
276         switch (status)\r
277         {\r
278                 case git_wc_status_none:\r
279                         return 0;\r
280                 case git_wc_status_unversioned:\r
281                         return 1;\r
282                 case git_wc_status_ignored:\r
283                         return 2;\r
284                 case git_wc_status_incomplete:\r
285                         return 4;\r
286                 case git_wc_status_normal:\r
287                 case git_wc_status_external:\r
288                         return 5;\r
289                 case git_wc_status_added:\r
290                         return 6;\r
291                 case git_wc_status_missing:\r
292                         return 7;\r
293                 case git_wc_status_deleted:\r
294                         return 8;\r
295                 case git_wc_status_replaced:\r
296                         return 9;\r
297                 case git_wc_status_modified:\r
298                         return 10;\r
299                 case git_wc_status_merged:\r
300                         return 11;\r
301                 case git_wc_status_conflicted:\r
302                         return 12;\r
303                 case git_wc_status_obstructed:\r
304                         return 13;\r
305         }\r
306         return 0;\r
307 }\r
308 \r
309 git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false */, bool noignore /* = false */, bool noexternals /* = false */)\r
310 {\r
311 #if 0\r
312         apr_hash_t *                            statushash;\r
313         apr_hash_t *                            exthash;\r
314         apr_array_header_t *            statusarray;\r
315         const sort_item*                        item;\r
316         \r
317         git_error_clear(m_err);\r
318         statushash = apr_hash_make(m_pool);\r
319         exthash = apr_hash_make(m_pool);\r
320         git_revnum_t youngest = Git_INVALID_REVNUM;\r
321         git_opt_revision_t rev;\r
322         rev.kind = git_opt_revision_unspecified;\r
323         struct hashbaton_t hashbaton;\r
324         hashbaton.hash = statushash;\r
325         hashbaton.exthash = exthash;\r
326         hashbaton.pThis = this;\r
327         m_err = git_client_status4 (&youngest,\r
328                                                         path.GetGitApiPath(m_pool),\r
329                                                         &rev,\r
330                                                         getstatushash,\r
331                                                         &hashbaton,\r
332                                                         git_depth_empty,                //depth\r
333                                                         TRUE,           //getall\r
334                                                         update,         //update\r
335                                                         noignore,               //noignore\r
336                                                         noexternals,\r
337                                                         NULL,\r
338                                                         ctx,\r
339                                                         m_pool);\r
340 \r
341 \r
342         // Error present if function is not under version control\r
343         if ((m_err != NULL) || (apr_hash_count(statushash) == 0))\r
344         {\r
345                 status = NULL;\r
346                 return -2;      \r
347         }\r
348 \r
349         // Convert the unordered hash to an ordered, sorted array\r
350         statusarray = sort_hash (statushash,\r
351                                                           sort_compare_items_as_paths,\r
352                                                           m_pool);\r
353 \r
354         // only the first entry is needed (no recurse)\r
355         item = &APR_ARRAY_IDX (statusarray, 0, const sort_item);\r
356         \r
357         status = (git_wc_status2_t *) item->value;\r
358         \r
359         return youngest;\r
360 #endif\r
361         return CString("");\r
362 }\r
363 \r
364 git_wc_status2_t * GitStatus::GetFirstFileStatus(const CTGitPath& path, CTGitPath& retPath, bool update, git_depth_t depth, bool bNoIgnore /* = true */, bool bNoExternals /* = false */)\r
365 {\r
366         static git_wc_status2 st;\r
367 /*\r
368         m_fileCache.Reset();\r
369 \r
370         m_fileCache.Init( CStringA( path.GetWinPathString().GetString() ) );\r
371 MessageBox(NULL, path.GetWinPathString(), _T("GetFirstFile"), MB_OK);\r
372         m_fileCache.m_pFileIter = m_fileCache.m_pFiles;\r
373         st.text_status = git_wc_status_none;\r
374 \r
375         if (m_fileCache.m_pFileIter)\r
376         {\r
377                 switch(m_fileCache.m_pFileIter->nStatus)\r
378                 {\r
379                 case WGFS_Normal: st.text_status = git_wc_status_normal; break;\r
380                 case WGFS_Modified: st.text_status = git_wc_status_modified; break;\r
381                 case WGFS_Deleted: st.text_status = git_wc_status_deleted; break;\r
382                 }\r
383 \r
384                 //retPath.SetFromGit((const char*)item->key);\r
385 \r
386                 m_fileCache.m_pFileIter = m_fileCache.m_pFileIter->pNext;\r
387         }\r
388 \r
389         return &st;\r
390 */\r
391 #if 0\r
392         const sort_item*                        item;\r
393 \r
394         git_error_clear(m_err);\r
395         m_statushash = apr_hash_make(m_pool);\r
396         m_externalhash = apr_hash_make(m_pool);\r
397         headrev = Git_INVALID_REVNUM;\r
398         git_opt_revision_t rev;\r
399         rev.kind = git_opt_revision_unspecified;\r
400         struct hashbaton_t hashbaton;\r
401         hashbaton.hash = m_statushash;\r
402         hashbaton.exthash = m_externalhash;\r
403         hashbaton.pThis = this;\r
404         m_statushashindex = 0;\r
405         m_err = git_client_status4 (&headrev,\r
406                                                         path.GetGitApiPath(m_pool),\r
407                                                         &rev,\r
408                                                         getstatushash,\r
409                                                         &hashbaton,\r
410                                                         depth,\r
411                                                         TRUE,           //getall\r
412                                                         update,         //update\r
413                                                         bNoIgnore,      //noignore\r
414                                                         bNoExternals,           //noexternals\r
415                                                         NULL,\r
416                                                         ctx,\r
417                                                         m_pool);\r
418 \r
419 \r
420         // Error present if function is not under version control\r
421         if ((m_err != NULL) || (apr_hash_count(m_statushash) == 0))\r
422         {\r
423                 return NULL;    \r
424         }\r
425 \r
426         // Convert the unordered hash to an ordered, sorted array\r
427         m_statusarray = sort_hash (m_statushash,\r
428                                                                 sort_compare_items_as_paths,\r
429                                                                 m_pool);\r
430 \r
431         // only the first entry is needed (no recurse)\r
432         m_statushashindex = 0;\r
433         item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
434         retPath.SetFromGit((const char*)item->key);\r
435         return (git_wc_status2_t *) item->value;\r
436 #endif\r
437 \r
438         return 0;\r
439 }\r
440 \r
441 unsigned int GitStatus::GetVersionedCount() const\r
442 {\r
443 //      return /**/m_fileCache.GetFileCount();\r
444 \r
445         unsigned int count = 0;\r
446 #if 0\r
447         const sort_item* item;\r
448         for (unsigned int i=0; i<apr_hash_count(m_statushash); ++i)\r
449         {\r
450                 item = &APR_ARRAY_IDX(m_statusarray, i, const sort_item);\r
451                 if (item)\r
452                 {\r
453                         if (GitStatus::GetMoreImportant(((git_wc_status_t *)item->value)->text_status, git_wc_status_ignored)!=git_wc_status_ignored)\r
454                                 count++;                                \r
455                 }\r
456         }\r
457 #endif\r
458         return count;\r
459 }\r
460 \r
461 git_wc_status2_t * GitStatus::GetNextFileStatus(CTGitPath& retPath)\r
462 {\r
463         static git_wc_status2 st;\r
464 \r
465         st.text_status = git_wc_status_none;\r
466 \r
467         /*if (m_fileCache.m_pFileIter)\r
468         {\r
469                 switch(m_fileCache.m_pFileIter->nStatus)\r
470                 {\r
471                 case WGFS_Normal: st.text_status = git_wc_status_normal; break;\r
472                 case WGFS_Modified: st.text_status = git_wc_status_modified; break;\r
473                 case WGFS_Deleted: st.text_status = git_wc_status_deleted; break;\r
474                 }\r
475 \r
476                 m_fileCache.m_pFileIter = m_fileCache.m_pFileIter->pNext;\r
477         }*/\r
478 \r
479         return &st;\r
480 \r
481 #if 0\r
482         const sort_item*                        item;\r
483 \r
484         if ((m_statushashindex+1) >= apr_hash_count(m_statushash))\r
485                 return NULL;\r
486         m_statushashindex++;\r
487 \r
488         item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
489         retPath.SetFromGit((const char*)item->key);\r
490         return (git_wc_status2_t *) item->value;\r
491 #endif\r
492         return 0;\r
493 }\r
494 \r
495 bool GitStatus::IsExternal(const CTGitPath& path) const\r
496 {\r
497 #if 0\r
498         if (apr_hash_get(m_externalhash, path.GetGitApiPath(m_pool), APR_HASH_KEY_STRING))\r
499                 return true;\r
500 #endif\r
501         return false;\r
502 }\r
503 \r
504 bool GitStatus::IsInExternal(const CTGitPath& path) const\r
505 {\r
506 #if 0\r
507         if (apr_hash_count(m_statushash) == 0)\r
508                 return false;\r
509 \r
510         GitPool localpool(m_pool);\r
511         apr_hash_index_t *hi;\r
512         const char* key;\r
513         for (hi = apr_hash_first(localpool, m_externalhash); hi; hi = apr_hash_next(hi)) \r
514         {\r
515                 apr_hash_this(hi, (const void**)&key, NULL, NULL);\r
516                 if (key)\r
517                 {\r
518                         if (CTGitPath(CUnicodeUtils::GetUnicode(key)).IsAncestorOf(path))\r
519                                 return true;\r
520                 }\r
521         }\r
522 #endif\r
523         return false;\r
524 }\r
525 \r
526 \r
527 void GitStatus::GetStatusString(git_wc_status_kind status, size_t buflen, TCHAR * string)\r
528 {\r
529         TCHAR * buf;\r
530         switch (status)\r
531         {\r
532                 case git_wc_status_none:\r
533                         buf = _T("none\0");\r
534                         break;\r
535                 case git_wc_status_unversioned:\r
536                         buf = _T("unversioned\0");\r
537                         break;\r
538                 case git_wc_status_normal:\r
539                         buf = _T("normal\0");\r
540                         break;\r
541                 case git_wc_status_added:\r
542                         buf = _T("added\0");\r
543                         break;\r
544                 case git_wc_status_missing:\r
545                         buf = _T("missing\0");\r
546                         break;\r
547                 case git_wc_status_deleted:\r
548                         buf = _T("deleted\0");\r
549                         break;\r
550                 case git_wc_status_replaced:\r
551                         buf = _T("replaced\0");\r
552                         break;\r
553                 case git_wc_status_modified:\r
554                         buf = _T("modified\0");\r
555                         break;\r
556                 case git_wc_status_merged:\r
557                         buf = _T("merged\0");\r
558                         break;\r
559                 case git_wc_status_conflicted:\r
560                         buf = _T("conflicted\0");\r
561                         break;\r
562                 case git_wc_status_obstructed:\r
563                         buf = _T("obstructed\0");\r
564                         break;\r
565                 case git_wc_status_ignored:\r
566                         buf = _T("ignored");\r
567                         break;\r
568                 case git_wc_status_external:\r
569                         buf = _T("external");\r
570                         break;\r
571                 case git_wc_status_incomplete:\r
572                         buf = _T("incomplete\0");\r
573                         break;\r
574                 default:\r
575                         buf = _T("\0");\r
576                         break;\r
577         }\r
578         _stprintf_s(string, buflen, _T("%s"), buf);\r
579 }\r
580 \r
581 void GitStatus::GetStatusString(HINSTANCE hInst, git_wc_status_kind status, TCHAR * string, int size, WORD lang)\r
582 {\r
583         switch (status)\r
584         {\r
585                 case git_wc_status_none:\r
586                         LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
587                         break;\r
588                 case git_wc_status_unversioned:\r
589                         LoadStringEx(hInst, IDS_STATUSUNVERSIONED, string, size, lang);\r
590                         break;\r
591                 case git_wc_status_normal:\r
592                         LoadStringEx(hInst, IDS_STATUSNORMAL, string, size, lang);\r
593                         break;\r
594                 case git_wc_status_added:\r
595                         LoadStringEx(hInst, IDS_STATUSADDED, string, size, lang);\r
596                         break;\r
597                 case git_wc_status_missing:\r
598                         LoadStringEx(hInst, IDS_STATUSABSENT, string, size, lang);\r
599                         break;\r
600                 case git_wc_status_deleted:\r
601                         LoadStringEx(hInst, IDS_STATUSDELETED, string, size, lang);\r
602                         break;\r
603                 case git_wc_status_replaced:\r
604                         LoadStringEx(hInst, IDS_STATUSREPLACED, string, size, lang);\r
605                         break;\r
606                 case git_wc_status_modified:\r
607                         LoadStringEx(hInst, IDS_STATUSMODIFIED, string, size, lang);\r
608                         break;\r
609                 case git_wc_status_merged:\r
610                         LoadStringEx(hInst, IDS_STATUSMERGED, string, size, lang);\r
611                         break;\r
612                 case git_wc_status_conflicted:\r
613                         LoadStringEx(hInst, IDS_STATUSCONFLICTED, string, size, lang);\r
614                         break;\r
615                 case git_wc_status_ignored:\r
616                         LoadStringEx(hInst, IDS_STATUSIGNORED, string, size, lang);\r
617                         break;\r
618                 case git_wc_status_obstructed:\r
619                         LoadStringEx(hInst, IDS_STATUSOBSTRUCTED, string, size, lang);\r
620                         break;\r
621                 case git_wc_status_external:\r
622                         LoadStringEx(hInst, IDS_STATUSEXTERNAL, string, size, lang);\r
623                         break;\r
624                 case git_wc_status_incomplete:\r
625                         LoadStringEx(hInst, IDS_STATUSINCOMPLETE, string, size, lang);\r
626                         break;\r
627                 default:\r
628                         LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
629                         break;\r
630         }\r
631 }\r
632 \r
633 #ifdef _MFC_VER\r
634 CString GitStatus::GetDepthString(git_depth_t depth)\r
635 {\r
636 #if 0\r
637         CString sDepth;\r
638         switch (depth)\r
639         {\r
640         case git_depth_unknown:\r
641                 sDepth.LoadString(IDS_Git_DEPTH_UNKNOWN);\r
642                 break;\r
643         case git_depth_empty:\r
644                 sDepth.LoadString(IDS_Git_DEPTH_EMPTY);\r
645                 break;\r
646         case git_depth_files:\r
647                 sDepth.LoadString(IDS_Git_DEPTH_FILES);\r
648                 break;\r
649         case git_depth_immediates:\r
650                 sDepth.LoadString(IDS_Git_DEPTH_IMMEDIATE);\r
651                 break;\r
652         case git_depth_infinity:\r
653                 sDepth.LoadString(IDS_Git_DEPTH_INFINITE);\r
654                 break;\r
655         }\r
656         return sDepth;\r
657 #endif\r
658         return CString("");\r
659 }\r
660 #endif\r
661 \r
662 void GitStatus::GetDepthString(HINSTANCE hInst, git_depth_t depth, TCHAR * string, int size, WORD lang)\r
663 {\r
664 #if 0\r
665         switch (depth)\r
666         {\r
667         case git_depth_unknown:\r
668                 LoadStringEx(hInst, IDS_SVN_DEPTH_UNKNOWN, string, size, lang);\r
669                 break;\r
670         case git_depth_empty:\r
671                 LoadStringEx(hInst, IDS_SVN_DEPTH_EMPTY, string, size, lang);\r
672                 break;\r
673         case git_depth_files:\r
674                 LoadStringEx(hInst, IDS_SVN_DEPTH_FILES, string, size, lang);\r
675                 break;\r
676         case git_depth_immediates:\r
677                 LoadStringEx(hInst, IDS_SVN_DEPTH_IMMEDIATE, string, size, lang);\r
678                 break;\r
679         case git_depth_infinity:\r
680                 LoadStringEx(hInst, IDS_SVN_DEPTH_INFINITE, string, size, lang);\r
681                 break;\r
682         }\r
683 #endif\r
684 }\r
685 \r
686 \r
687 int GitStatus::LoadStringEx(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax, WORD wLanguage)\r
688 {\r
689         const STRINGRESOURCEIMAGE* pImage;\r
690         const STRINGRESOURCEIMAGE* pImageEnd;\r
691         ULONG nResourceSize;\r
692         HGLOBAL hGlobal;\r
693         UINT iIndex;\r
694         int ret;\r
695 \r
696         HRSRC hResource =  FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE(((uID>>4)+1)), wLanguage);\r
697         if (!hResource)\r
698         {\r
699                 // try the default language before giving up!\r
700                 hResource = FindResource(hInstance, MAKEINTRESOURCE(((uID>>4)+1)), RT_STRING);\r
701                 if (!hResource)\r
702                         return 0;\r
703         }\r
704         hGlobal = LoadResource(hInstance, hResource);\r
705         if (!hGlobal)\r
706                 return 0;\r
707         pImage = (const STRINGRESOURCEIMAGE*)::LockResource(hGlobal);\r
708         if(!pImage)\r
709                 return 0;\r
710 \r
711         nResourceSize = ::SizeofResource(hInstance, hResource);\r
712         pImageEnd = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+nResourceSize);\r
713         iIndex = uID&0x000f;\r
714 \r
715         while ((iIndex > 0) && (pImage < pImageEnd))\r
716         {\r
717                 pImage = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+(sizeof(STRINGRESOURCEIMAGE)+(pImage->nLength*sizeof(WCHAR))));\r
718                 iIndex--;\r
719         }\r
720         if (pImage >= pImageEnd)\r
721                 return 0;\r
722         if (pImage->nLength == 0)\r
723                 return 0;\r
724 \r
725         ret = pImage->nLength;\r
726         if (pImage->nLength > nBufferMax)\r
727         {\r
728                 wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength-1);\r
729                 lpBuffer[nBufferMax-1] = 0;\r
730         }\r
731         else\r
732         {\r
733                 wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength);\r
734                 lpBuffer[ret] = 0;\r
735         }\r
736         return ret;\r
737 }\r
738 \r
739 BOOL GitStatus::getallstatus(const struct wgFile_s *pFile, void *pUserData)\r
740 {\r
741         git_wc_status_kind * s = (git_wc_status_kind *)pUserData;\r
742         *s = GitStatus::GetMoreImportant(*s, GitStatusFromWingit(pFile->nStatus));\r
743         return FALSE;\r
744 }\r
745 \r
746 #if 0\r
747 git_error_t * GitStatus::getallstatus(void * baton, const char * /*path*/, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
748 {\r
749         git_wc_status_kind * s = (git_wc_status_kind *)baton;\r
750         *s = GitStatus::GetMoreImportant(*s, status->text_status);\r
751         *s = GitStatus::GetMoreImportant(*s, status->prop_status);\r
752         return Git_NO_ERROR;\r
753 }\r
754 #endif\r
755 \r
756 #if 0\r
757 git_error_t * GitStatus::getstatushash(void * baton, const char * path, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
758 {\r
759         hashbaton_t * hash = (hashbaton_t *)baton;\r
760         const StdStrAVector& filterList = hash->pThis->m_filterFileList;\r
761         if (status->text_status == git_wc_status_external)\r
762         {\r
763                 apr_hash_set (hash->exthash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, (const void*)1);\r
764                 return Git_NO_ERROR;\r
765         }\r
766         if(filterList.size() > 0)\r
767         {\r
768                 // We have a filter active - we're only interested in files which are in \r
769                 // the filter  \r
770                 if(!binary_search(filterList.begin(), filterList.end(), path))\r
771                 {\r
772                         // This item is not in the filter - don't store it\r
773                         return Git_NO_ERROR;\r
774                 }\r
775         }\r
776         git_wc_status2_t * statuscopy = git_wc_dup_status2 (status, hash->pThis->m_pool);\r
777         apr_hash_set (hash->hash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, statuscopy);\r
778         return Git_NO_ERROR;\r
779 }\r
780 \r
781 apr_array_header_t * GitStatus::sort_hash (apr_hash_t *ht,\r
782                                                                                 int (*comparison_func) (const GitStatus::sort_item *, const GitStatus::sort_item *),\r
783                                                                                 apr_pool_t *pool)\r
784 {\r
785         apr_hash_index_t *hi;\r
786         apr_array_header_t *ary;\r
787 \r
788         /* allocate an array with only one element to begin with. */\r
789         ary = apr_array_make (pool, 1, sizeof(sort_item));\r
790 \r
791         /* loop over hash table and push all keys into the array */\r
792         for (hi = apr_hash_first (pool, ht); hi; hi = apr_hash_next (hi))\r
793         {\r
794                 sort_item *item = (sort_item*)apr_array_push (ary);\r
795 \r
796                 apr_hash_this (hi, &item->key, &item->klen, &item->value);\r
797         }\r
798 \r
799         /* now quick sort the array.  */\r
800         qsort (ary->elts, ary->nelts, ary->elt_size,\r
801                 (int (*)(const void *, const void *))comparison_func);\r
802 \r
803         return ary;\r
804 }\r
805 \r
806 int GitStatus::sort_compare_items_as_paths (const sort_item *a, const sort_item *b)\r
807 {\r
808         const char *astr, *bstr;\r
809 \r
810         astr = (const char*)a->key;\r
811         bstr = (const char*)b->key;\r
812         return git_path_compare_paths (astr, bstr);\r
813 }\r
814 #endif\r
815 \r
816 git_error_t* GitStatus::cancel(void *baton)\r
817 {\r
818 #if 0\r
819         volatile bool * canceled = (bool *)baton;\r
820         if (*canceled)\r
821         {\r
822                 CString temp;\r
823                 temp.LoadString(IDS_Git_USERCANCELLED);\r
824                 return git_error_create(Git_ERR_CANCELLED, NULL, CUnicodeUtils::GetUTF8(temp));\r
825         }\r
826         return Git_NO_ERROR;\r
827 #endif \r
828         return 0;\r
829 }\r
830 \r
831 #ifdef _MFC_VER\r
832 \r
833 // Set-up a filter to restrict the files which will have their status stored by a get-status\r
834 void GitStatus::SetFilter(const CTGitPathList& fileList)\r
835 {\r
836         m_filterFileList.clear();\r
837         for(int fileIndex = 0; fileIndex < fileList.GetCount(); fileIndex++)\r
838         {\r
839 //              m_filterFileList.push_back(fileList[fileIndex].GetGitApiPath(m_pool));\r
840         }\r
841         // Sort the list so that we can do binary searches\r
842         std::sort(m_filterFileList.begin(), m_filterFileList.end());\r
843 }\r
844 \r
845 void GitStatus::ClearFilter()\r
846 {\r
847         m_filterFileList.clear();\r
848 }\r
849 \r
850 #endif // _MFC_VER\r
851 \r