OSDN Git Service

3b9ad9a007c96522568107286ae01df0e361bc8b
[tortoisegit/TortoiseGitJp.git] / src / Git / Git.cpp
1 #include "StdAfx.h"\r
2 #include "Git.h"\r
3 #include "atlconv.h"\r
4 #include "GitRev.h"\r
5 #include "registry.h"\r
6 #include "GitConfig.h"\r
7 \r
8 \r
9 static LPTSTR nextpath(LPCTSTR src, LPTSTR dst, UINT maxlen)\r
10 {\r
11         LPCTSTR orgsrc;\r
12 \r
13         while (*src == _T(';'))\r
14                 src++;\r
15 \r
16         orgsrc = src;\r
17 \r
18         if (!--maxlen)\r
19                 goto nullterm;\r
20 \r
21         while (*src && *src != _T(';'))\r
22         {\r
23                 if (*src != _T('"'))\r
24                 {\r
25                         *dst++ = *src++;\r
26                         if (!--maxlen)\r
27                         {\r
28                                 orgsrc = src;\r
29                                 goto nullterm;\r
30                         }\r
31                 }\r
32                 else\r
33                 {\r
34                         src++;\r
35                         while (*src && *src != _T('"'))\r
36                         {\r
37                                 *dst++ = *src++;\r
38                                 if (!--maxlen)\r
39                                 {\r
40                                         orgsrc = src;\r
41                                         goto nullterm;\r
42                                 }\r
43                         }\r
44 \r
45                         if (*src)\r
46                                 src++;\r
47                 }\r
48         }\r
49 \r
50         while (*src == _T(';'))\r
51                 src++;\r
52 \r
53 nullterm:\r
54 \r
55         *dst = 0;\r
56 \r
57         return (orgsrc != src) ? (LPTSTR)src : NULL;\r
58 }\r
59 \r
60 static inline BOOL FileExists(LPCTSTR lpszFileName)\r
61 {\r
62         struct _stat st;\r
63         return _tstat(lpszFileName, &st) == 0;\r
64 }\r
65 \r
66 static BOOL FindGitPath()\r
67 {\r
68         size_t size;\r
69         _tgetenv_s(&size, NULL, 0, _T("PATH"));\r
70 \r
71         if (!size)\r
72         {\r
73                 return FALSE;\r
74         }\r
75 \r
76         TCHAR *env = (TCHAR*)alloca(size * sizeof(TCHAR));\r
77         _tgetenv_s(&size, env, size, _T("PATH"));\r
78 \r
79         TCHAR buf[_MAX_PATH];\r
80 \r
81         // search in all paths defined in PATH\r
82         while ((env = nextpath(env, buf, _MAX_PATH-1)) && *buf)\r
83         {\r
84                 TCHAR *pfin = buf + _tcslen(buf)-1;\r
85 \r
86                 // ensure trailing slash\r
87                 if (*pfin != _T('/') && *pfin != _T('\\'))\r
88                         _tcscpy(++pfin, _T("\\"));\r
89 \r
90                 const int len = _tcslen(buf);\r
91 \r
92                 if ((len + 7) < _MAX_PATH)\r
93                         _tcscpy(pfin+1, _T("git.exe"));\r
94                 else\r
95                         break;\r
96 \r
97                 if ( FileExists(buf) )\r
98                 {\r
99                         // dir found\r
100                         return TRUE;\r
101                 }\r
102         }\r
103 \r
104         return FALSE;\r
105 }\r
106 \r
107 \r
108 #define MAX_DIRBUFFER 1000\r
109 CString CGit::ms_LastMsysGitDir;\r
110 CGit g_Git;\r
111 BOOL g_IsWingitDllload = TRUE;\r
112 \r
113 LPBYTE wgGetRevisionID_safe(const char *pszProjectPath, const char *pszName)\r
114 {\r
115         if(g_IsWingitDllload)\r
116                 return wgGetRevisionID(pszProjectPath,pszName);\r
117         else\r
118                 return NULL;\r
119 }\r
120 \r
121 BOOL wgEnumFiles_safe(const char *pszProjectPath, const char *pszSubPath, unsigned int nFlags, WGENUMFILECB *pEnumCb, void *pUserData)\r
122 {\r
123         if(g_IsWingitDllload)\r
124                 return wgEnumFiles(pszProjectPath,pszSubPath,nFlags,pEnumCb,pUserData);\r
125         else\r
126                 return FALSE;\r
127 }\r
128 \r
129 BOOL CGit::IsVista()\r
130 {\r
131         OSVERSIONINFO osvi;\r
132     BOOL bIsWindowsXPorLater;\r
133 \r
134     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));\r
135     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
136 \r
137     GetVersionEx(&osvi);\r
138         \r
139         if(osvi.dwMajorVersion >= 6)\r
140                 return TRUE;\r
141         else\r
142                 return FALSE;\r
143 }\r
144 \r
145 static void InitWinGitDll()\r
146 {\r
147         __try\r
148         {\r
149 \r
150                 if( CGit::IsVista () )\r
151                 {\r
152                         g_IsWingitDllload=FALSE;\r
153                         return;\r
154                 }\r
155                 if ( !wgInit() )\r
156                 {\r
157                                 // TODO\r
158                 }\r
159         }\r
160         __except(1)\r
161         {\r
162                 g_IsWingitDllload=FALSE;\r
163                 return;\r
164         }\r
165 \r
166 }\r
167 CGit::CGit(void)\r
168 {\r
169         GetCurrentDirectory(MAX_DIRBUFFER,m_CurrentDir.GetBuffer(MAX_DIRBUFFER));\r
170         m_CurrentDir.ReleaseBuffer();\r
171         // make sure git/bin is in PATH before wingit.dll gets (delay) loaded by wgInit()\r
172         if ( !CheckMsysGitDir() )\r
173         {\r
174                 // TODO\r
175         }\r
176         InitWinGitDll();\r
177 }\r
178 \r
179 CGit::~CGit(void)\r
180 {\r
181 }\r
182 \r
183 static char g_Buffer[4096];\r
184 \r
185 int CGit::RunAsync(CString cmd,PROCESS_INFORMATION *piOut,HANDLE *hReadOut,CString *StdioFile)\r
186 {\r
187         SECURITY_ATTRIBUTES sa;\r
188         HANDLE hRead, hWrite;\r
189         HANDLE hStdioFile = NULL;\r
190 \r
191         sa.nLength = sizeof(SECURITY_ATTRIBUTES);\r
192         sa.lpSecurityDescriptor=NULL;\r
193         sa.bInheritHandle=TRUE;\r
194         if(!CreatePipe(&hRead,&hWrite,&sa,0))\r
195         {\r
196                 return GIT_ERROR_OPEN_PIP;\r
197         }\r
198         \r
199         if(StdioFile)\r
200         {\r
201                 hStdioFile=CreateFile(*StdioFile,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
202                         &sa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);  \r
203         }\r
204 \r
205         STARTUPINFO si;\r
206         PROCESS_INFORMATION pi;\r
207         si.cb=sizeof(STARTUPINFO);\r
208         GetStartupInfo(&si);\r
209 \r
210         si.hStdError=hWrite;\r
211         if(StdioFile)\r
212                 si.hStdOutput=hStdioFile;\r
213         else\r
214                 si.hStdOutput=hWrite;\r
215 \r
216         si.wShowWindow=SW_HIDE;\r
217         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
218 \r
219         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
220         {\r
221                 LPVOID lpMsgBuf;\r
222                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
223                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
224                         (LPTSTR)&lpMsgBuf,\r
225                         0,NULL);\r
226                 return GIT_ERROR_CREATE_PROCESS;\r
227         }\r
228         \r
229         CloseHandle(hWrite);\r
230         if(piOut)\r
231                 *piOut=pi;\r
232         if(hReadOut)\r
233                 *hReadOut=hRead;\r
234         \r
235         return 0;\r
236 \r
237 }\r
238 //Must use sperate function to convert ANSI str to union code string\r
239 //Becuase A2W use stack as internal convert buffer. \r
240 void CGit::StringAppend(CString *str,BYTE *p,int code,int length)\r
241 {\r
242      //USES_CONVERSION;\r
243          //str->Append(A2W_CP((LPCSTR)p,code));\r
244         WCHAR * buf;\r
245 \r
246         int len ;\r
247         if(length<0)\r
248                 len= strlen((const char*)p);\r
249         else\r
250                 len=length;\r
251         //if (len==0)\r
252         //      return ;\r
253         //buf = new WCHAR[len*4 + 1];\r
254         buf = str->GetBuffer(len*4+1+str->GetLength())+str->GetLength();\r
255         SecureZeroMemory(buf, (len*4 + 1)*sizeof(WCHAR));\r
256         MultiByteToWideChar(code, 0, (LPCSTR)p, len, buf, len*4);\r
257         str->ReleaseBuffer();\r
258         //str->Append(buf);\r
259         //delete buf;\r
260 }       \r
261 BOOL CGit::IsInitRepos()\r
262 {\r
263         CString cmdout;\r
264         cmdout.Empty();\r
265         if(g_Git.Run(_T("git.exe rev-parse --revs-only HEAD"),&cmdout,CP_UTF8))\r
266         {\r
267         //      CMessageBox::Show(NULL,cmdout,_T("TortoiseGit"),MB_OK);\r
268                 return TRUE;\r
269         }\r
270         if(cmdout.IsEmpty())\r
271                 return TRUE;\r
272 \r
273         return FALSE;\r
274 }\r
275 int CGit::Run(CString cmd,BYTE_VECTOR *vector)\r
276 {\r
277         PROCESS_INFORMATION pi;\r
278         HANDLE hRead;\r
279         if(RunAsync(cmd,&pi,&hRead))\r
280                 return GIT_ERROR_CREATE_PROCESS;\r
281 \r
282         DWORD readnumber;\r
283         BYTE data;\r
284         while(ReadFile(hRead,&data,1,&readnumber,NULL))\r
285         {\r
286                 //g_Buffer[readnumber]=0;\r
287                 vector->push_back(data);\r
288 //              StringAppend(output,g_Buffer,codes);\r
289         }\r
290 \r
291         \r
292         CloseHandle(pi.hThread);\r
293 \r
294         WaitForSingleObject(pi.hProcess, INFINITE);\r
295         DWORD exitcode =0;\r
296 \r
297         if(!GetExitCodeProcess(pi.hProcess,&exitcode))\r
298         {\r
299                 return GIT_ERROR_GET_EXIT_CODE;\r
300         }\r
301 \r
302         CloseHandle(pi.hProcess);\r
303 \r
304         CloseHandle(hRead);\r
305         return exitcode;\r
306 \r
307 }\r
308 int CGit::Run(CString cmd, CString* output,int code)\r
309 {\r
310         BYTE_VECTOR vector;\r
311         int ret;\r
312         ret=Run(cmd,&vector);\r
313 \r
314         vector.push_back(0);\r
315         \r
316         StringAppend(output,&(vector[0]),code);\r
317         return ret;\r
318 }\r
319 \r
320 CString CGit::GetUserName(void)\r
321 {\r
322         CString UserName;\r
323         Run(_T("git.exe config user.name"),&UserName,CP_UTF8);\r
324         return UserName;\r
325 }\r
326 CString CGit::GetUserEmail(void)\r
327 {\r
328         CString UserName;\r
329         Run(_T("git.exe config user.email"),&UserName,CP_UTF8);\r
330         return UserName;\r
331 }\r
332 \r
333 CString CGit::GetCurrentBranch(void)\r
334 {\r
335         CString output;\r
336         //Run(_T("git.exe branch"),&branch);\r
337 \r
338         int ret=g_Git.Run(_T("git.exe branch"),&output,CP_UTF8);\r
339         if(!ret)\r
340         {               \r
341                 int pos=0;\r
342                 CString one;\r
343                 while( pos>=0 )\r
344                 {\r
345                         //i++;\r
346                         one=output.Tokenize(_T("\n"),pos);\r
347                         //list.push_back(one.Right(one.GetLength()-2));\r
348                         if(one[0] == _T('*'))\r
349                                 return one.Right(one.GetLength()-2);\r
350                 }\r
351         }\r
352         return CString("");\r
353 }\r
354 \r
355 int CGit::BuildOutputFormat(CString &format,bool IsFull)\r
356 {\r
357         CString log;\r
358         log.Format(_T("#<%c>%%x00"),LOG_REV_ITEM_BEGIN);\r
359         format += log;\r
360         if(IsFull)\r
361         {\r
362                 log.Format(_T("#<%c>%%an%%x00"),LOG_REV_AUTHOR_NAME);\r
363                 format += log;\r
364                 log.Format(_T("#<%c>%%ae%%x00"),LOG_REV_AUTHOR_EMAIL);\r
365                 format += log;\r
366                 log.Format(_T("#<%c>%%ai%%x00"),LOG_REV_AUTHOR_DATE);\r
367                 format += log;\r
368                 log.Format(_T("#<%c>%%cn%%x00"),LOG_REV_COMMIT_NAME);\r
369                 format += log;\r
370                 log.Format(_T("#<%c>%%ce%%x00"),LOG_REV_COMMIT_EMAIL);\r
371                 format += log;\r
372                 log.Format(_T("#<%c>%%ci%%x00"),LOG_REV_COMMIT_DATE);\r
373                 format += log;\r
374                 log.Format(_T("#<%c>%%s%%x00"),LOG_REV_COMMIT_SUBJECT);\r
375                 format += log;\r
376                 log.Format(_T("#<%c>%%b%%x00"),LOG_REV_COMMIT_BODY);\r
377                 format += log;\r
378         }\r
379         log.Format(_T("#<%c>%%m%%H%%x00"),LOG_REV_COMMIT_HASH);\r
380         format += log;\r
381         log.Format(_T("#<%c>%%P%%x00"),LOG_REV_COMMIT_PARENT);\r
382         format += log;\r
383 \r
384         if(IsFull)\r
385         {\r
386                 log.Format(_T("#<%c>%%x00"),LOG_REV_COMMIT_FILE);\r
387                 format += log;\r
388         }\r
389         return 0;\r
390 }\r
391 \r
392 int CGit::GetLog(BYTE_VECTOR& logOut, CString &hash,  CTGitPath *path ,int count,int mask)\r
393 {\r
394 \r
395         CString cmd;\r
396         CString log;\r
397         CString num;\r
398         CString since;\r
399 \r
400         CString file;\r
401 \r
402         if(path)\r
403                 file.Format(_T(" -- \"%s\""),path->GetGitPathString());\r
404         \r
405         if(count>0)\r
406                 num.Format(_T("-n%d"),count);\r
407 \r
408         CString param;\r
409 \r
410         if(mask& LOG_INFO_STAT )\r
411                 param += _T(" --numstat ");\r
412         if(mask& LOG_INFO_FILESTATE)\r
413                 param += _T(" --raw ");\r
414 \r
415         if(mask& LOG_INFO_FULLHISTORY)\r
416                 param += _T(" --full-history ");\r
417 \r
418         if(mask& LOG_INFO_BOUNDARY)\r
419                 param += _T(" --left-right --boundary ");\r
420 \r
421         if(mask& CGit::LOG_INFO_ALL_BRANCH)\r
422                 param += _T(" --all ");\r
423 \r
424         if(mask& CGit::LOG_INFO_DETECT_COPYRENAME)\r
425                 param += _T(" -C ");\r
426         \r
427         if(mask& CGit::LOG_INFO_DETECT_RENAME )\r
428                 param += _T(" -M ");\r
429 \r
430         if(mask& CGit::LOG_INFO_FIRST_PARENT )\r
431                 param += _T(" --first-parent ");\r
432         \r
433         if(mask& CGit::LOG_INFO_NO_MERGE )\r
434                 param += _T(" --no-merges ");\r
435 \r
436         if(mask& CGit::LOG_INFO_FOLLOW)\r
437                 param += _T(" --follow ");\r
438 \r
439         param+=hash;\r
440 \r
441         cmd.Format(_T("git.exe log %s -z --topo-order %s --parents --pretty=format:\""),\r
442                                 num,param);\r
443 \r
444         BuildOutputFormat(log,!(mask&CGit::LOG_INFO_ONLY_HASH));\r
445 \r
446         cmd += log;\r
447         cmd += CString(_T("\"  "))+hash+file;\r
448 \r
449         return Run(cmd,&logOut);\r
450 }\r
451 \r
452 #if 0\r
453 int CGit::GetShortLog(CString &logOut,CTGitPath * path, int count)\r
454 {\r
455         CString cmd;\r
456         CString log;\r
457         int n;\r
458         if(count<0)\r
459                 n=100;\r
460         else\r
461                 n=count;\r
462         cmd.Format(_T("git.exe log --left-right --boundary --topo-order -n%d --pretty=format:\""),n);\r
463         BuildOutputFormat(log,false);\r
464         cmd += log+_T("\"");\r
465         if (path)\r
466                 cmd+= _T("  -- \"")+path->GetGitPathString()+_T("\"");\r
467         //cmd += CString(_T("\" HEAD~40..HEAD"));\r
468         return Run(cmd,&logOut);\r
469 }\r
470 #endif\r
471 \r
472 #define BUFSIZE 512\r
473 void GetTempPath(CString &path)\r
474 {\r
475         TCHAR lpPathBuffer[BUFSIZE];\r
476         DWORD dwRetVal;\r
477         DWORD dwBufSize=BUFSIZE;\r
478         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
479                            lpPathBuffer); // buffer for path \r
480     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
481     {\r
482         path=_T("");\r
483     }\r
484         path.Format(_T("%s"),lpPathBuffer);\r
485 }\r
486 CString GetTempFile()\r
487 {\r
488         TCHAR lpPathBuffer[BUFSIZE];\r
489         DWORD dwRetVal;\r
490     DWORD dwBufSize=BUFSIZE;\r
491         TCHAR szTempName[BUFSIZE];  \r
492         UINT uRetVal;\r
493 \r
494         dwRetVal = GetTempPath(dwBufSize,     // length of the buffer\r
495                            lpPathBuffer); // buffer for path \r
496     if (dwRetVal > dwBufSize || (dwRetVal == 0))\r
497     {\r
498         return _T("");\r
499     }\r
500          // Create a temporary file. \r
501     uRetVal = GetTempFileName(lpPathBuffer, // directory for tmp files\r
502                               TEXT("Patch"),  // temp file name prefix \r
503                               0,            // create unique name \r
504                               szTempName);  // buffer for name \r
505 \r
506 \r
507     if (uRetVal == 0)\r
508     {\r
509         return _T("");\r
510     }\r
511 \r
512         return CString(szTempName);\r
513 \r
514 }\r
515 \r
516 int CGit::RunLogFile(CString cmd,CString &filename)\r
517 {\r
518         STARTUPINFO si;\r
519         PROCESS_INFORMATION pi;\r
520         si.cb=sizeof(STARTUPINFO);\r
521         GetStartupInfo(&si);\r
522 \r
523         SECURITY_ATTRIBUTES   psa={sizeof(psa),NULL,TRUE};;   \r
524         psa.bInheritHandle=TRUE;   \r
525     \r
526         HANDLE   houtfile=CreateFile(filename,GENERIC_WRITE,FILE_SHARE_READ   |   FILE_SHARE_WRITE,   \r
527                         &psa,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);   \r
528 \r
529 \r
530         si.wShowWindow=SW_HIDE;\r
531         si.dwFlags=STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;\r
532         si.hStdOutput   =   houtfile; \r
533         \r
534         if(!CreateProcess(NULL,(LPWSTR)cmd.GetString(), NULL,NULL,TRUE,NULL,NULL,(LPWSTR)m_CurrentDir.GetString(),&si,&pi))\r
535         {\r
536                 LPVOID lpMsgBuf;\r
537                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_FROM_SYSTEM,\r
538                         NULL,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
539                         (LPTSTR)&lpMsgBuf,\r
540                         0,NULL);\r
541                 return GIT_ERROR_CREATE_PROCESS;\r
542         }\r
543         \r
544         WaitForSingleObject(pi.hProcess,INFINITE);   \r
545         \r
546         CloseHandle(pi.hThread);\r
547         CloseHandle(pi.hProcess);\r
548         CloseHandle(houtfile);\r
549         return GIT_SUCCESS;\r
550 //      return 0;\r
551 }\r
552 \r
553 git_revnum_t CGit::GetHash(CString &friendname)\r
554 {\r
555         // NOTE: could replace this with wgGetRevisionID call\r
556 \r
557         CString cmd;\r
558         CString out;\r
559         cmd.Format(_T("git.exe rev-parse %s" ),friendname);\r
560         Run(cmd,&out,CP_UTF8);\r
561         int pos=out.ReverseFind(_T('\n'));\r
562         if(pos>0)\r
563                 return out.Left(pos);\r
564         return out;\r
565 }\r
566 \r
567 int CGit::GetTagList(STRING_VECTOR &list)\r
568 {\r
569         int ret;\r
570         CString cmd,output;\r
571         cmd=_T("git.exe tag -l");\r
572         int i=0;\r
573         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
574         if(!ret)\r
575         {               \r
576                 int pos=0;\r
577                 CString one;\r
578                 while( pos>=0 )\r
579                 {\r
580                         i++;\r
581                         one=output.Tokenize(_T("\n"),pos);\r
582                         list.push_back(one);\r
583                 }\r
584         }\r
585         return ret;\r
586 }\r
587 \r
588 int CGit::GetBranchList(STRING_VECTOR &list,int *current,BRANCH_TYPE type)\r
589 {\r
590         int ret;\r
591         CString cmd,output;\r
592         cmd=_T("git.exe branch");\r
593 \r
594         if(type==(BRANCH_LOCAL|BRANCH_REMOTE))\r
595                 cmd+=_T(" -a");\r
596         else if(type==BRANCH_REMOTE)\r
597                 cmd+=_T(" -r");\r
598 \r
599         int i=0;\r
600         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
601         if(!ret)\r
602         {               \r
603                 int pos=0;\r
604                 CString one;\r
605                 while( pos>=0 )\r
606                 {\r
607                         one=output.Tokenize(_T("\n"),pos);\r
608                         list.push_back(one.Right(one.GetLength()-2));\r
609                         if(one[0] == _T('*'))\r
610                                 if(current)\r
611                                         *current=i;\r
612                         i++;\r
613                 }\r
614         }\r
615         return ret;\r
616 }\r
617 \r
618 int CGit::GetRemoteList(STRING_VECTOR &list)\r
619 {\r
620         int ret;\r
621         CString cmd,output;\r
622         cmd=_T("git.exe config  --get-regexp remote.*.url");\r
623         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
624         if(!ret)\r
625         {\r
626                 int pos=0;\r
627                 CString one;\r
628                 while( pos>=0 )\r
629                 {\r
630                         one=output.Tokenize(_T("\n"),pos);\r
631                         int start=one.Find(_T("."),0);\r
632                         if(start>0)\r
633                         {\r
634                                 CString url;\r
635                                 url=one.Right(one.GetLength()-start-1);\r
636                                 one=url;\r
637                                 one=one.Left(one.Find(_T("."),0));\r
638                                 list.push_back(one);\r
639                         }\r
640                 }\r
641         }\r
642         return ret;\r
643 }\r
644 \r
645 int CGit::GetMapHashToFriendName(MAP_HASH_NAME &map)\r
646 {\r
647         int ret;\r
648         CString cmd,output;\r
649         cmd=_T("git show-ref -d");\r
650         ret=g_Git.Run(cmd,&output,CP_UTF8);\r
651         if(!ret)\r
652         {\r
653                 int pos=0;\r
654                 CString one;\r
655                 while( pos>=0 )\r
656                 {\r
657                         one=output.Tokenize(_T("\n"),pos);\r
658                         int start=one.Find(_T(" "),0);\r
659                         if(start>0)\r
660                         {\r
661                                 CString name;\r
662                                 name=one.Right(one.GetLength()-start-1);\r
663 \r
664                                 CString hash;\r
665                                 hash=one.Left(start);\r
666 \r
667                                 map[hash].push_back(name);\r
668                         }\r
669                 }\r
670         }\r
671         return ret;\r
672 }\r
673 \r
674 BOOL CGit::CheckMsysGitDir()\r
675 {\r
676         static BOOL bInitialized = FALSE;\r
677 \r
678         if (bInitialized)\r
679         {\r
680                 return TRUE;\r
681         }\r
682 \r
683         TCHAR *oldpath,*home;\r
684         size_t size;\r
685 \r
686         // set HOME if not set already\r
687         _tgetenv_s(&size, NULL, 0, _T("HOME"));\r
688         if (!size)\r
689         {\r
690                 _tdupenv_s(&home,&size,_T("USERPROFILE")); \r
691                 _tputenv_s(_T("HOME"),home);\r
692                 free(home);\r
693         }\r
694 \r
695         //setup ssh client\r
696         CRegString sshclient=CRegString(_T("Software\\TortoiseGit\\SSH"));\r
697         CString ssh=sshclient;\r
698 \r
699         if(!ssh.IsEmpty())\r
700         {\r
701                 _tputenv_s(_T("GIT_SSH"),ssh);\r
702         }else\r
703         {\r
704                 _tputenv_s(_T("GIT_SSH"),_T(""));\r
705         }\r
706 \r
707         // search PATH if git/bin directory is alredy present\r
708         if ( FindGitPath() )\r
709         {\r
710                 bInitialized = TRUE;\r
711                 return TRUE;\r
712         }\r
713 \r
714         // add git/bin path to PATH\r
715 \r
716         CRegString msysdir=CRegString(REG_MSYSGIT_PATH,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
717         CString str=msysdir;\r
718         if(str.IsEmpty())\r
719         {\r
720                 CRegString msysinstalldir=CRegString(REG_MSYSGIT_INSTALL,_T(""),FALSE,HKEY_LOCAL_MACHINE);\r
721                 str=msysinstalldir;\r
722                 if ( !str.IsEmpty() )\r
723                 {\r
724                         str += (str[str.GetLength()-1] != '\\') ? "\\bin" : "bin";\r
725                         msysdir=str;\r
726                         msysdir.write();\r
727                 }\r
728                 else\r
729                 {\r
730                         return false;\r
731                 }\r
732         }\r
733         //CGit::m_MsysGitPath=str;\r
734 \r
735         //set path\r
736 \r
737         _tdupenv_s(&oldpath,&size,_T("PATH")); \r
738 \r
739         CString path;\r
740         path.Format(_T("%s;%s"),oldpath,str);\r
741 \r
742         _tputenv_s(_T("PATH"),path);\r
743 \r
744         free(oldpath);\r
745 \r
746 \r
747     if( !FindGitPath() )\r
748         {\r
749                 return false;\r
750         }\r
751         else\r
752         {\r
753                 bInitialized = TRUE;\r
754                 return true;\r
755         }\r
756 }\r