OSDN Git Service

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