OSDN Git Service

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