OSDN Git Service

Change Dir Structure to be same as TortoiseSVN'
[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;\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         statuskind = git_wc_status_none;\r
212         err = git_client_status4 (&youngest,\r
213                                                         path.GetGitApiPath(pool),\r
214                                                         &rev,\r
215                                                         getallstatus,\r
216                                                         &statuskind,\r
217                                                         depth,\r
218                                                         TRUE,           //getall\r
219                                                         FALSE,          //update\r
220                                                         TRUE,           //noignore\r
221                                                         FALSE,          //ignore externals\r
222                                                         NULL,\r
223                                                         ctx,\r
224                                                         pool);\r
225 \r
226         // Error present\r
227         if (err != NULL)\r
228         {\r
229                 git_error_clear(err);\r
230                 git_pool_destroy (pool);                                //free allocated memory\r
231                 return git_wc_status_none;      \r
232         }\r
233 \r
234         git_pool_destroy (pool);                                //free allocated memory\r
235 #endif\r
236         return statuskind;\r
237 }\r
238 \r
239 // static method\r
240 git_wc_status_kind GitStatus::GetAllStatusRecursive(const CTGitPath& path)\r
241 {\r
242         return GetAllStatus(path, git_depth_infinity);\r
243 }\r
244 \r
245 // static method\r
246 git_wc_status_kind GitStatus::GetMoreImportant(git_wc_status_kind status1, git_wc_status_kind status2)\r
247 {\r
248         if (GetStatusRanking(status1) >= GetStatusRanking(status2))\r
249                 return status1;\r
250         return status2;\r
251 }\r
252 // static private method\r
253 int GitStatus::GetStatusRanking(git_wc_status_kind status)\r
254 {\r
255         switch (status)\r
256         {\r
257                 case git_wc_status_none:\r
258                         return 0;\r
259                 case git_wc_status_unversioned:\r
260                         return 1;\r
261                 case git_wc_status_ignored:\r
262                         return 2;\r
263                 case git_wc_status_incomplete:\r
264                         return 4;\r
265                 case git_wc_status_normal:\r
266                 case git_wc_status_external:\r
267                         return 5;\r
268                 case git_wc_status_added:\r
269                         return 6;\r
270                 case git_wc_status_missing:\r
271                         return 7;\r
272                 case git_wc_status_deleted:\r
273                         return 8;\r
274                 case git_wc_status_replaced:\r
275                         return 9;\r
276                 case git_wc_status_modified:\r
277                         return 10;\r
278                 case git_wc_status_merged:\r
279                         return 11;\r
280                 case git_wc_status_conflicted:\r
281                         return 12;\r
282                 case git_wc_status_obstructed:\r
283                         return 13;\r
284         }\r
285         return 0;\r
286 }\r
287 \r
288 git_revnum_t GitStatus::GetStatus(const CTGitPath& path, bool update /* = false */, bool noignore /* = false */, bool noexternals /* = false */)\r
289 {\r
290 #if 0\r
291         apr_hash_t *                            statushash;\r
292         apr_hash_t *                            exthash;\r
293         apr_array_header_t *            statusarray;\r
294         const sort_item*                        item;\r
295         \r
296         git_error_clear(m_err);\r
297         statushash = apr_hash_make(m_pool);\r
298         exthash = apr_hash_make(m_pool);\r
299         git_revnum_t youngest = Git_INVALID_REVNUM;\r
300         git_opt_revision_t rev;\r
301         rev.kind = git_opt_revision_unspecified;\r
302         struct hashbaton_t hashbaton;\r
303         hashbaton.hash = statushash;\r
304         hashbaton.exthash = exthash;\r
305         hashbaton.pThis = this;\r
306         m_err = git_client_status4 (&youngest,\r
307                                                         path.GetGitApiPath(m_pool),\r
308                                                         &rev,\r
309                                                         getstatushash,\r
310                                                         &hashbaton,\r
311                                                         git_depth_empty,                //depth\r
312                                                         TRUE,           //getall\r
313                                                         update,         //update\r
314                                                         noignore,               //noignore\r
315                                                         noexternals,\r
316                                                         NULL,\r
317                                                         ctx,\r
318                                                         m_pool);\r
319 \r
320 \r
321         // Error present if function is not under version control\r
322         if ((m_err != NULL) || (apr_hash_count(statushash) == 0))\r
323         {\r
324                 status = NULL;\r
325                 return -2;      \r
326         }\r
327 \r
328         // Convert the unordered hash to an ordered, sorted array\r
329         statusarray = sort_hash (statushash,\r
330                                                           sort_compare_items_as_paths,\r
331                                                           m_pool);\r
332 \r
333         // only the first entry is needed (no recurse)\r
334         item = &APR_ARRAY_IDX (statusarray, 0, const sort_item);\r
335         \r
336         status = (git_wc_status2_t *) item->value;\r
337         \r
338         return youngest;\r
339 #endif\r
340         return CString("");\r
341 }\r
342 git_wc_status2_t * GitStatus::GetFirstFileStatus(const CTGitPath& path, CTGitPath& retPath, bool update, git_depth_t depth, bool bNoIgnore /* = true */, bool bNoExternals /* = false */)\r
343 {\r
344 #if 0\r
345         const sort_item*                        item;\r
346 \r
347         git_error_clear(m_err);\r
348         m_statushash = apr_hash_make(m_pool);\r
349         m_externalhash = apr_hash_make(m_pool);\r
350         headrev = Git_INVALID_REVNUM;\r
351         git_opt_revision_t rev;\r
352         rev.kind = git_opt_revision_unspecified;\r
353         struct hashbaton_t hashbaton;\r
354         hashbaton.hash = m_statushash;\r
355         hashbaton.exthash = m_externalhash;\r
356         hashbaton.pThis = this;\r
357         m_statushashindex = 0;\r
358         m_err = git_client_status4 (&headrev,\r
359                                                         path.GetGitApiPath(m_pool),\r
360                                                         &rev,\r
361                                                         getstatushash,\r
362                                                         &hashbaton,\r
363                                                         depth,\r
364                                                         TRUE,           //getall\r
365                                                         update,         //update\r
366                                                         bNoIgnore,      //noignore\r
367                                                         bNoExternals,           //noexternals\r
368                                                         NULL,\r
369                                                         ctx,\r
370                                                         m_pool);\r
371 \r
372 \r
373         // Error present if function is not under version control\r
374         if ((m_err != NULL) || (apr_hash_count(m_statushash) == 0))\r
375         {\r
376                 return NULL;    \r
377         }\r
378 \r
379         // Convert the unordered hash to an ordered, sorted array\r
380         m_statusarray = sort_hash (m_statushash,\r
381                                                                 sort_compare_items_as_paths,\r
382                                                                 m_pool);\r
383 \r
384         // only the first entry is needed (no recurse)\r
385         m_statushashindex = 0;\r
386         item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
387         retPath.SetFromGit((const char*)item->key);\r
388         return (git_wc_status2_t *) item->value;\r
389 #endif\r
390 \r
391         return 0;\r
392 }\r
393 \r
394 unsigned int GitStatus::GetVersionedCount() const\r
395 {\r
396 \r
397         unsigned int count = 0;\r
398 #if 0\r
399         const sort_item* item;\r
400         for (unsigned int i=0; i<apr_hash_count(m_statushash); ++i)\r
401         {\r
402                 item = &APR_ARRAY_IDX(m_statusarray, i, const sort_item);\r
403                 if (item)\r
404                 {\r
405                         if (GitStatus::GetMoreImportant(((git_wc_status_t *)item->value)->text_status, git_wc_status_ignored)!=git_wc_status_ignored)\r
406                                 count++;                                \r
407                 }\r
408         }\r
409 #endif\r
410         return count;\r
411 }\r
412 \r
413 git_wc_status2_t * GitStatus::GetNextFileStatus(CTGitPath& retPath)\r
414 {\r
415 #if 0\r
416         const sort_item*                        item;\r
417 \r
418         if ((m_statushashindex+1) >= apr_hash_count(m_statushash))\r
419                 return NULL;\r
420         m_statushashindex++;\r
421 \r
422         item = &APR_ARRAY_IDX (m_statusarray, m_statushashindex, const sort_item);\r
423         retPath.SetFromGit((const char*)item->key);\r
424         return (git_wc_status2_t *) item->value;\r
425 #endif\r
426         return 0;\r
427 }\r
428 \r
429 bool GitStatus::IsExternal(const CTGitPath& path) const\r
430 {\r
431 #if 0\r
432         if (apr_hash_get(m_externalhash, path.GetGitApiPath(m_pool), APR_HASH_KEY_STRING))\r
433                 return true;\r
434 #endif\r
435         return false;\r
436 }\r
437 \r
438 bool GitStatus::IsInExternal(const CTGitPath& path) const\r
439 {\r
440 #if 0\r
441         if (apr_hash_count(m_statushash) == 0)\r
442                 return false;\r
443 \r
444         GitPool localpool(m_pool);\r
445         apr_hash_index_t *hi;\r
446         const char* key;\r
447         for (hi = apr_hash_first(localpool, m_externalhash); hi; hi = apr_hash_next(hi)) \r
448         {\r
449                 apr_hash_this(hi, (const void**)&key, NULL, NULL);\r
450                 if (key)\r
451                 {\r
452                         if (CTGitPath(CUnicodeUtils::GetUnicode(key)).IsAncestorOf(path))\r
453                                 return true;\r
454                 }\r
455         }\r
456 #endif\r
457         return false;\r
458 }\r
459 \r
460 \r
461 void GitStatus::GetStatusString(git_wc_status_kind status, size_t buflen, TCHAR * string)\r
462 {\r
463         TCHAR * buf;\r
464         switch (status)\r
465         {\r
466                 case git_wc_status_none:\r
467                         buf = _T("none\0");\r
468                         break;\r
469                 case git_wc_status_unversioned:\r
470                         buf = _T("unversioned\0");\r
471                         break;\r
472                 case git_wc_status_normal:\r
473                         buf = _T("normal\0");\r
474                         break;\r
475                 case git_wc_status_added:\r
476                         buf = _T("added\0");\r
477                         break;\r
478                 case git_wc_status_missing:\r
479                         buf = _T("missing\0");\r
480                         break;\r
481                 case git_wc_status_deleted:\r
482                         buf = _T("deleted\0");\r
483                         break;\r
484                 case git_wc_status_replaced:\r
485                         buf = _T("replaced\0");\r
486                         break;\r
487                 case git_wc_status_modified:\r
488                         buf = _T("modified\0");\r
489                         break;\r
490                 case git_wc_status_merged:\r
491                         buf = _T("merged\0");\r
492                         break;\r
493                 case git_wc_status_conflicted:\r
494                         buf = _T("conflicted\0");\r
495                         break;\r
496                 case git_wc_status_obstructed:\r
497                         buf = _T("obstructed\0");\r
498                         break;\r
499                 case git_wc_status_ignored:\r
500                         buf = _T("ignored");\r
501                         break;\r
502                 case git_wc_status_external:\r
503                         buf = _T("external");\r
504                         break;\r
505                 case git_wc_status_incomplete:\r
506                         buf = _T("incomplete\0");\r
507                         break;\r
508                 default:\r
509                         buf = _T("\0");\r
510                         break;\r
511         }\r
512         _stprintf_s(string, buflen, _T("%s"), buf);\r
513 }\r
514 \r
515 void GitStatus::GetStatusString(HINSTANCE hInst, git_wc_status_kind status, TCHAR * string, int size, WORD lang)\r
516 {\r
517         switch (status)\r
518         {\r
519                 case git_wc_status_none:\r
520                         LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
521                         break;\r
522                 case git_wc_status_unversioned:\r
523                         LoadStringEx(hInst, IDS_STATUSUNVERSIONED, string, size, lang);\r
524                         break;\r
525                 case git_wc_status_normal:\r
526                         LoadStringEx(hInst, IDS_STATUSNORMAL, string, size, lang);\r
527                         break;\r
528                 case git_wc_status_added:\r
529                         LoadStringEx(hInst, IDS_STATUSADDED, string, size, lang);\r
530                         break;\r
531                 case git_wc_status_missing:\r
532                         LoadStringEx(hInst, IDS_STATUSABSENT, string, size, lang);\r
533                         break;\r
534                 case git_wc_status_deleted:\r
535                         LoadStringEx(hInst, IDS_STATUSDELETED, string, size, lang);\r
536                         break;\r
537                 case git_wc_status_replaced:\r
538                         LoadStringEx(hInst, IDS_STATUSREPLACED, string, size, lang);\r
539                         break;\r
540                 case git_wc_status_modified:\r
541                         LoadStringEx(hInst, IDS_STATUSMODIFIED, string, size, lang);\r
542                         break;\r
543                 case git_wc_status_merged:\r
544                         LoadStringEx(hInst, IDS_STATUSMERGED, string, size, lang);\r
545                         break;\r
546                 case git_wc_status_conflicted:\r
547                         LoadStringEx(hInst, IDS_STATUSCONFLICTED, string, size, lang);\r
548                         break;\r
549                 case git_wc_status_ignored:\r
550                         LoadStringEx(hInst, IDS_STATUSIGNORED, string, size, lang);\r
551                         break;\r
552                 case git_wc_status_obstructed:\r
553                         LoadStringEx(hInst, IDS_STATUSOBSTRUCTED, string, size, lang);\r
554                         break;\r
555                 case git_wc_status_external:\r
556                         LoadStringEx(hInst, IDS_STATUSEXTERNAL, string, size, lang);\r
557                         break;\r
558                 case git_wc_status_incomplete:\r
559                         LoadStringEx(hInst, IDS_STATUSINCOMPLETE, string, size, lang);\r
560                         break;\r
561                 default:\r
562                         LoadStringEx(hInst, IDS_STATUSNONE, string, size, lang);\r
563                         break;\r
564         }\r
565 }\r
566 \r
567 #ifdef _MFC_VER\r
568 CString GitStatus::GetDepthString(git_depth_t depth)\r
569 {\r
570 #if 0\r
571         CString sDepth;\r
572         switch (depth)\r
573         {\r
574         case git_depth_unknown:\r
575                 sDepth.LoadString(IDS_Git_DEPTH_UNKNOWN);\r
576                 break;\r
577         case git_depth_empty:\r
578                 sDepth.LoadString(IDS_Git_DEPTH_EMPTY);\r
579                 break;\r
580         case git_depth_files:\r
581                 sDepth.LoadString(IDS_Git_DEPTH_FILES);\r
582                 break;\r
583         case git_depth_immediates:\r
584                 sDepth.LoadString(IDS_Git_DEPTH_IMMEDIATE);\r
585                 break;\r
586         case git_depth_infinity:\r
587                 sDepth.LoadString(IDS_Git_DEPTH_INFINITE);\r
588                 break;\r
589         }\r
590         return sDepth;\r
591 #endif\r
592         return CString("");\r
593 }\r
594 #endif\r
595 \r
596 void GitStatus::GetDepthString(HINSTANCE hInst, git_depth_t depth, TCHAR * string, int size, WORD lang)\r
597 {\r
598 #if 0\r
599         switch (depth)\r
600         {\r
601         case git_depth_unknown:\r
602                 LoadStringEx(hInst, IDS_SVN_DEPTH_UNKNOWN, string, size, lang);\r
603                 break;\r
604         case git_depth_empty:\r
605                 LoadStringEx(hInst, IDS_SVN_DEPTH_EMPTY, string, size, lang);\r
606                 break;\r
607         case git_depth_files:\r
608                 LoadStringEx(hInst, IDS_SVN_DEPTH_FILES, string, size, lang);\r
609                 break;\r
610         case git_depth_immediates:\r
611                 LoadStringEx(hInst, IDS_SVN_DEPTH_IMMEDIATE, string, size, lang);\r
612                 break;\r
613         case git_depth_infinity:\r
614                 LoadStringEx(hInst, IDS_SVN_DEPTH_INFINITE, string, size, lang);\r
615                 break;\r
616         }\r
617 #endif\r
618 }\r
619 \r
620 \r
621 int GitStatus::LoadStringEx(HINSTANCE hInstance, UINT uID, LPTSTR lpBuffer, int nBufferMax, WORD wLanguage)\r
622 {\r
623         const STRINGRESOURCEIMAGE* pImage;\r
624         const STRINGRESOURCEIMAGE* pImageEnd;\r
625         ULONG nResourceSize;\r
626         HGLOBAL hGlobal;\r
627         UINT iIndex;\r
628         int ret;\r
629 \r
630         HRSRC hResource =  FindResourceEx(hInstance, RT_STRING, MAKEINTRESOURCE(((uID>>4)+1)), wLanguage);\r
631         if (!hResource)\r
632         {\r
633                 // try the default language before giving up!\r
634                 hResource = FindResource(hInstance, MAKEINTRESOURCE(((uID>>4)+1)), RT_STRING);\r
635                 if (!hResource)\r
636                         return 0;\r
637         }\r
638         hGlobal = LoadResource(hInstance, hResource);\r
639         if (!hGlobal)\r
640                 return 0;\r
641         pImage = (const STRINGRESOURCEIMAGE*)::LockResource(hGlobal);\r
642         if(!pImage)\r
643                 return 0;\r
644 \r
645         nResourceSize = ::SizeofResource(hInstance, hResource);\r
646         pImageEnd = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+nResourceSize);\r
647         iIndex = uID&0x000f;\r
648 \r
649         while ((iIndex > 0) && (pImage < pImageEnd))\r
650         {\r
651                 pImage = (const STRINGRESOURCEIMAGE*)(LPBYTE(pImage)+(sizeof(STRINGRESOURCEIMAGE)+(pImage->nLength*sizeof(WCHAR))));\r
652                 iIndex--;\r
653         }\r
654         if (pImage >= pImageEnd)\r
655                 return 0;\r
656         if (pImage->nLength == 0)\r
657                 return 0;\r
658 \r
659         ret = pImage->nLength;\r
660         if (pImage->nLength > nBufferMax)\r
661         {\r
662                 wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength-1);\r
663                 lpBuffer[nBufferMax-1] = 0;\r
664         }\r
665         else\r
666         {\r
667                 wcsncpy_s(lpBuffer, nBufferMax, pImage->achString, pImage->nLength);\r
668                 lpBuffer[ret] = 0;\r
669         }\r
670         return ret;\r
671 }\r
672 \r
673 #if 0\r
674 git_error_t * GitStatus::getallstatus(void * baton, const char * /*path*/, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
675 {\r
676         git_wc_status_kind * s = (git_wc_status_kind *)baton;\r
677         *s = GitStatus::GetMoreImportant(*s, status->text_status);\r
678         *s = GitStatus::GetMoreImportant(*s, status->prop_status);\r
679         return Git_NO_ERROR;\r
680 }\r
681 #endif\r
682 \r
683 #if 0\r
684 git_error_t * GitStatus::getstatushash(void * baton, const char * path, git_wc_status2_t * status, apr_pool_t * /*pool*/)\r
685 {\r
686         hashbaton_t * hash = (hashbaton_t *)baton;\r
687         const StdStrAVector& filterList = hash->pThis->m_filterFileList;\r
688         if (status->text_status == git_wc_status_external)\r
689         {\r
690                 apr_hash_set (hash->exthash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, (const void*)1);\r
691                 return Git_NO_ERROR;\r
692         }\r
693         if(filterList.size() > 0)\r
694         {\r
695                 // We have a filter active - we're only interested in files which are in \r
696                 // the filter  \r
697                 if(!binary_search(filterList.begin(), filterList.end(), path))\r
698                 {\r
699                         // This item is not in the filter - don't store it\r
700                         return Git_NO_ERROR;\r
701                 }\r
702         }\r
703         git_wc_status2_t * statuscopy = git_wc_dup_status2 (status, hash->pThis->m_pool);\r
704         apr_hash_set (hash->hash, apr_pstrdup(hash->pThis->m_pool, path), APR_HASH_KEY_STRING, statuscopy);\r
705         return Git_NO_ERROR;\r
706 }\r
707 \r
708 apr_array_header_t * GitStatus::sort_hash (apr_hash_t *ht,\r
709                                                                                 int (*comparison_func) (const GitStatus::sort_item *, const GitStatus::sort_item *),\r
710                                                                                 apr_pool_t *pool)\r
711 {\r
712         apr_hash_index_t *hi;\r
713         apr_array_header_t *ary;\r
714 \r
715         /* allocate an array with only one element to begin with. */\r
716         ary = apr_array_make (pool, 1, sizeof(sort_item));\r
717 \r
718         /* loop over hash table and push all keys into the array */\r
719         for (hi = apr_hash_first (pool, ht); hi; hi = apr_hash_next (hi))\r
720         {\r
721                 sort_item *item = (sort_item*)apr_array_push (ary);\r
722 \r
723                 apr_hash_this (hi, &item->key, &item->klen, &item->value);\r
724         }\r
725 \r
726         /* now quick sort the array.  */\r
727         qsort (ary->elts, ary->nelts, ary->elt_size,\r
728                 (int (*)(const void *, const void *))comparison_func);\r
729 \r
730         return ary;\r
731 }\r
732 \r
733 int GitStatus::sort_compare_items_as_paths (const sort_item *a, const sort_item *b)\r
734 {\r
735         const char *astr, *bstr;\r
736 \r
737         astr = (const char*)a->key;\r
738         bstr = (const char*)b->key;\r
739         return git_path_compare_paths (astr, bstr);\r
740 }\r
741 #endif\r
742 \r
743 git_error_t* GitStatus::cancel(void *baton)\r
744 {\r
745 #if 0\r
746         volatile bool * canceled = (bool *)baton;\r
747         if (*canceled)\r
748         {\r
749                 CString temp;\r
750                 temp.LoadString(IDS_Git_USERCANCELLED);\r
751                 return git_error_create(Git_ERR_CANCELLED, NULL, CUnicodeUtils::GetUTF8(temp));\r
752         }\r
753         return Git_NO_ERROR;\r
754 #endif \r
755         return 0;\r
756 }\r
757 \r
758 #ifdef _MFC_VER\r
759 \r
760 // Set-up a filter to restrict the files which will have their status stored by a get-status\r
761 void GitStatus::SetFilter(const CTGitPathList& fileList)\r
762 {\r
763         m_filterFileList.clear();\r
764         for(int fileIndex = 0; fileIndex < fileList.GetCount(); fileIndex++)\r
765         {\r
766 //              m_filterFileList.push_back(fileList[fileIndex].GetGitApiPath(m_pool));\r
767         }\r
768         // Sort the list so that we can do binary searches\r
769         std::sort(m_filterFileList.begin(), m_filterFileList.end());\r
770 }\r
771 \r
772 void GitStatus::ClearFilter()\r
773 {\r
774         m_filterFileList.clear();\r
775 }\r
776 \r
777 #endif // _MFC_VER\r
778 \r