OSDN Git Service

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